94 lines
11 KiB
C#
94 lines
11 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using HotUpdate.Gameplay;
|
|
using Newtonsoft.Json.Linq;
|
|
using UnityEditor;
|
|
using UnityEditor.SceneManagement;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
using Object=UnityEngine.Object;
|
|
|
|
/// <summary>Persistent, independent skill review. Never edits the production arena or account.</summary>
|
|
public static class BuildSkillSlice
|
|
{
|
|
public const string Folder="Assets/Bundles/Combat/SkillSlice";
|
|
public const string Prefab=Folder+"/SkillSlice.prefab";
|
|
public const string Scene="Assets/Bundles/Scenes/Review/SkillSlice_Review.unity";
|
|
static readonly string[] Names={"FireCharge","Fireball","FireHit","RockHit","Shield"};
|
|
static readonly string[] SoundNames={"FireCharge","FireLaunch","FireHit","RockHit","Shield"};
|
|
static void Folders(string path){if(AssetDatabase.IsValidFolder(path))return;string parent=Path.GetDirectoryName(path).Replace('\\','/');Folders(parent);AssetDatabase.CreateFolder(parent,Path.GetFileName(path));}
|
|
static ParticleSystem Part(Transform parent,string name,Color color,int count,float life,float size,bool loop=false,Mesh mesh=null)
|
|
{
|
|
var go=new GameObject(name);go.transform.SetParent(parent,false);go.layer=30;var ps=go.AddComponent<ParticleSystem>();
|
|
var main=ps.main;main.playOnAwake=false;main.loop=loop;main.duration=.5f;main.startLifetime=life;main.startSpeed=mesh!=null?0:.25f;main.startSize=size;main.startColor=color;main.maxParticles=32;main.simulationSpace=ParticleSystemSimulationSpace.Local;
|
|
var emission=ps.emission;emission.rateOverTime=loop?count:0;if(!loop)emission.SetBursts(new[]{new ParticleSystem.Burst(0,(short)count)});
|
|
var shape=ps.shape;shape.shapeType=ParticleSystemShapeType.Sphere;shape.radius=loop?.035f:.08f;
|
|
var colorLife=ps.colorOverLifetime;colorLife.enabled=true;var gradient=new Gradient();gradient.SetKeys(new[]{new GradientColorKey(Color.white,0),new GradientColorKey(color,1)},new[]{new GradientAlphaKey(.85f,0),new GradientAlphaKey(0,1)});colorLife.color=gradient;
|
|
var sizeLife=ps.sizeOverLifetime;sizeLife.enabled=true;sizeLife.size=new ParticleSystem.MinMaxCurve(1,AnimationCurve.Linear(0,1,1,.1f));
|
|
var renderer=ps.GetComponent<ParticleSystemRenderer>();renderer.sharedMaterial=AssetDatabase.LoadAssetAtPath<Material>("Assets/Bundles/Effects/EnemyCombat/CombatGlow.mat");renderer.renderMode=mesh==null?ParticleSystemRenderMode.Billboard:ParticleSystemRenderMode.Mesh;if(mesh!=null)renderer.mesh=mesh;
|
|
return ps;
|
|
}
|
|
static float Height(Transform root)
|
|
{
|
|
float top=0;var mesh=new Mesh();foreach(var skin in root.GetComponentsInChildren<SkinnedMeshRenderer>(true)){skin.BakeMesh(mesh,true);foreach(var v in mesh.vertices)top=Mathf.Max(top,root.InverseTransformPoint(skin.transform.TransformPoint(v)).y);}Object.DestroyImmediate(mesh);return top;
|
|
}
|
|
public static string Build()
|
|
{
|
|
if(EditorApplication.isPlaying)throw new Exception("Author in Edit Mode");Folders(Folder);
|
|
AssetDatabase.ImportAsset(Folder+"/trace.json",ImportAssetOptions.ForceUpdate);var trace=AssetDatabase.LoadAssetAtPath<TextAsset>(Folder+"/trace.json");var data=JObject.Parse(trace.text);
|
|
var previous=SceneManager.GetActiveScene();var scene=EditorSceneManager.NewScene(NewSceneSetup.EmptyScene,NewSceneMode.Additive);
|
|
try
|
|
{
|
|
SceneManager.SetActiveScene(scene);var root=new GameObject("SkillSlice");var player=root.AddComponent<SkillSlicePlayer>();
|
|
var camera=new GameObject("SkillSliceCamera").AddComponent<Camera>();camera.transform.SetParent(root.transform,false);camera.transform.localPosition=new Vector3(8,9,-11);camera.transform.LookAt(new Vector3(0,.5f,1.1f));camera.orthographic=true;camera.orthographicSize=4.4f;camera.cullingMask=1<<30;camera.clearFlags=CameraClearFlags.SolidColor;camera.backgroundColor=new Color(.09f,.13f,.17f);camera.depth=100;
|
|
var light=new GameObject("SkillSliceLight").AddComponent<Light>();light.transform.SetParent(root.transform,false);light.type=LightType.Directional;light.intensity=1.3f;light.transform.rotation=Quaternion.Euler(40,-35,0);light.cullingMask=1<<30;
|
|
var floor=GameObject.CreatePrimitive(PrimitiveType.Plane);floor.name="Ground_Y0";floor.transform.SetParent(root.transform,false);floor.transform.localScale=new Vector3(.6f,1,1);floor.transform.localPosition=new Vector3(0,-.005f,1);floor.GetComponent<Renderer>().sharedMaterial=AssetDatabase.LoadAssetAtPath<Material>("Assets/Bundles/Scenes/Review/EnemyReviewFloor.mat");Object.DestroyImmediate(floor.GetComponent<Collider>());
|
|
var so=new SerializedObject(player);so.FindProperty("_trace").objectReferenceValue=trace;
|
|
var views=so.FindProperty("_views");views.arraySize=((JArray)data["initial"]).Count;
|
|
int index=0;
|
|
foreach(var u in (JArray)data["initial"])
|
|
{
|
|
int id=(int)u["id"];string actor=id==0?"RockBall":id==1?"FireCat":"Hornlet",kind=id<100?"Animal":"Enemy";
|
|
var slot=new GameObject("Entity"+id).transform;slot.SetParent(root.transform,false);slot.localPosition=new Vector3(0,0,(int)u["z"]/1000f);slot.localRotation=Quaternion.Euler(0,id<100?180:0,0);
|
|
string suffix=id<100?"Companion":"Enemy";var model=(GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Bundles/Characters/"+kind+"/"+actor+"Studio/"+actor+"Studio_"+suffix+".prefab"),slot);
|
|
model.transform.localScale=Vector3.one*((id<100?1.5f:1.2f)/Height(model.transform));
|
|
var muzzle=new GameObject("Muzzle").transform;muzzle.SetParent(slot,false);muzzle.localPosition=new Vector3(0,.8f,-.48f);
|
|
var label=new GameObject("State").AddComponent<TextMesh>();label.transform.SetParent(slot,false);label.transform.localPosition=new Vector3(0,1.85f,0);label.transform.rotation=camera.transform.rotation;label.fontSize=60;label.characterSize=.032f;label.anchor=TextAnchor.MiddleCenter;label.color=Color.white;
|
|
string recipe="../Config/Art/"+(id==1?"Companions":"EnemyCharacters")+"/"+actor+".json";float impact=(float)JObject.Parse(File.ReadAllText(recipe))["attackImpact"];
|
|
var v=views.GetArrayElementAtIndex(index++);v.FindPropertyRelative("id").intValue=id;v.FindPropertyRelative("root").objectReferenceValue=slot;v.FindPropertyRelative("muzzle").objectReferenceValue=muzzle;v.FindPropertyRelative("label").objectReferenceValue=label;v.FindPropertyRelative("animator").objectReferenceValue=model.GetComponentInChildren<Animator>();v.FindPropertyRelative("impact").floatValue=impact;
|
|
}
|
|
var ring=AssetDatabase.LoadAssetAtPath<Mesh>("Assets/Bundles/Effects/EnemyCombat/CombatRing.asset");
|
|
const string corePath=Folder+"/FireballCore.asset";var core=AssetDatabase.LoadAssetAtPath<Mesh>(corePath);
|
|
if(core==null){var sphere=GameObject.CreatePrimitive(PrimitiveType.Sphere);core=Object.Instantiate(sphere.GetComponent<MeshFilter>().sharedMesh);core.name="FireballCore";Object.DestroyImmediate(sphere);AssetDatabase.CreateAsset(core,corePath);}
|
|
var effects=so.FindProperty("_effects");effects.arraySize=5;
|
|
for(int i=0;i<5;i++)
|
|
{
|
|
bool loop=i==0||i==1||i==4;Color color=i==4?new Color(.35f,.85f,1):i==3?new Color(1,.78f,.35f):new Color(1,.28f,.025f);
|
|
var authored=Part(root.transform,"Vfx_Skill_"+Names[i],color,loop?12:14,i==4?.35f:i<2?.2f:.35f,i==4?2.3f:i==1?.45f:i==0?.25f:.15f,loop,i==4?ring:null);
|
|
if(i<4){var renderer=authored.GetComponent<ParticleSystemRenderer>();renderer.renderMode=ParticleSystemRenderMode.Mesh;renderer.mesh=core;}
|
|
if(i==4){var main=authored.main;main.startColor=new Color(.35f,.85f,1,.22f);main.startSize=1.8f;main.startLifetime=.6f;var emission=authored.emission;emission.rateOverTime=4;}
|
|
if(i==2||i==3){var flash=Part(authored.transform,"ImpactRing",color,1,.25f,1.35f,false,ring);var size=flash.sizeOverLifetime;size.size=new ParticleSystem.MinMaxCurve(1,AnimationCurve.Linear(0,.3f,1,1.2f));}
|
|
if(i==1)Part(authored.transform,"BrightCore",new Color(1,.85f,.25f),20,.12f,.2f,true);
|
|
var asset=PrefabUtility.SaveAsPrefabAsset(authored.gameObject,Folder+"/Vfx_Skill_"+Names[i]+".prefab");Object.DestroyImmediate(authored.gameObject);
|
|
var instances=effects.GetArrayElementAtIndex(i).FindPropertyRelative("instances");instances.arraySize=i==1?8:4;
|
|
for(int n=0;n<instances.arraySize;n++){var go=(GameObject)PrefabUtility.InstantiatePrefab(asset,root.transform);instances.GetArrayElementAtIndex(n).objectReferenceValue=go.GetComponent<ParticleSystem>();}
|
|
}
|
|
var clips=so.FindProperty("_clips");clips.arraySize=5;
|
|
for(int i=0;i<5;i++)
|
|
{
|
|
string path="Assets/Bundles/Sound/SFX/BattleSkills/Sfx_"+SoundNames[i]+".wav";AssetDatabase.ImportAsset(path,ImportAssetOptions.ForceUpdate);var importer=(AudioImporter)AssetImporter.GetAtPath(path);if(importer==null)throw new Exception("Missing "+path);
|
|
var sample=importer.defaultSampleSettings;sample.loadType=AudioClipLoadType.DecompressOnLoad;sample.compressionFormat=AudioCompressionFormat.PCM;sample.sampleRateSetting=AudioSampleRateSetting.PreserveSampleRate;importer.defaultSampleSettings=sample;importer.forceToMono=false;importer.SaveAndReimport();clips.GetArrayElementAtIndex(i).objectReferenceValue=AssetDatabase.LoadAssetAtPath<AudioClip>(path);
|
|
}
|
|
var voices=so.FindProperty("_voices");voices.arraySize=8;
|
|
for(int i=0;i<8;i++){var go=new GameObject("Voice"+i);go.transform.SetParent(root.transform,false);var voice=go.AddComponent<AudioSource>();voice.playOnAwake=false;voice.spatialBlend=0;voice.volume=.7f/8;voices.GetArrayElementAtIndex(i).objectReferenceValue=voice;}
|
|
var feedback=(GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Bundles/Effects/EnemyCombat/EnemyCombatPresentation.prefab"),root.transform);so.FindProperty("_enemyFeedback").objectReferenceValue=feedback.GetComponent<EnemyCombatPresentation>();
|
|
var status=new GameObject("TraceStatus").AddComponent<TextMesh>();status.transform.SetParent(root.transform,false);status.transform.localPosition=new Vector3(0,.3f,-3.5f);status.transform.rotation=camera.transform.rotation;status.fontSize=60;status.characterSize=.04f;status.anchor=TextAnchor.MiddleCenter;status.color=new Color(.8f,.95f,1);so.FindProperty("_status").objectReferenceValue=status;
|
|
so.ApplyModifiedPropertiesWithoutUndo();foreach(var t in root.GetComponentsInChildren<Transform>(true))t.gameObject.layer=30;
|
|
PrefabUtility.SaveAsPrefabAsset(root,Prefab);Object.DestroyImmediate(root);
|
|
PrefabUtility.InstantiatePrefab(AssetDatabase.LoadAssetAtPath<GameObject>(Prefab),scene);EditorSceneManager.SaveScene(scene,Scene);AssetDatabase.SaveAssets();return "Saved independent "+Prefab+" and "+Scene;
|
|
}
|
|
finally{SceneManager.SetActiveScene(previous);EditorSceneManager.CloseScene(scene,true);}
|
|
}
|
|
}
|