void RenderAsInstances(List <TTexturePointBlockAndScore> Instances) { var mf = GetComponent <MeshFilter> (); var mr = GetComponent <MeshRenderer> (); var TriangleMesh = mf.sharedMesh; var TriangleMaterial = mr.sharedMaterial; int PointSplit = TriangleMesh.triangles.Length / 3; List <Matrix4x4> InstanceCaches = null; int RunningPointCount = 0; var MtxIdentityList = new List <Matrix4x4> () { Matrix4x4.identity }; int InstancesDrawn = 0; int WastedPoints = 0; int BiggestInstanceCacheCount = 0; System.Action Flush = () => { if (InstanceCaches != null && InstanceCaches.Count > 0) { var InstanceUniforms = new MaterialPropertyBlock(); InstanceUniforms.SetMatrixArray(TexturePointBlocksUniform, InstanceCaches); InstanceUniforms.SetFloat(TexturePointBlockCountUniform, InstanceCaches.Count); // draw with instancing to draw in scene editor, but we don't wanna use it on mobile because of north american s6 #if UNITY_EDITOR Graphics.DrawMeshInstanced(TriangleMesh, 0, TriangleMaterial, MtxIdentityList, InstanceUniforms); #else Graphics.DrawMesh(TriangleMesh, Matrix4x4.identity, TriangleMaterial, 0, Camera.main, 0, InstanceUniforms); #endif InstancesDrawn += MtxIdentityList.Count; BiggestInstanceCacheCount = Mathf.Max(BiggestInstanceCacheCount, InstanceCaches.Count); } InstanceCaches = new List <Matrix4x4>(); RunningPointCount = 0; }; // init Flush(); // iterate and break up for (int i = 0; i < Instances.Count; i++) { var Block = Instances [i].Block; if (InstanceCaches.Count >= TTEXTUREPOINTBLOCK_MAX) { WastedPoints += PointSplit - RunningPointCount; Flush(); } // have we overflowed? if (Block.LodPointCount + RunningPointCount > PointSplit) { WastedPoints += PointSplit - RunningPointCount; Flush(); } RunningPointCount += Block.LodPointCount; InstanceCaches.Add(Block.DataMatrix); } Flush(); #if UNITY_EDITOR //Debug.Log ("Meshes drawn=" + InstancesDrawn + " wasted points=" + WastedPoints + " BiggestInstanceCacheCount="+BiggestInstanceCacheCount); #endif }
public static void Apply(this AnimatorState dest, AnimatorState source) { dest.cycleOffsetParameter = source.cycleOffsetParameter; dest.cycleOffset = source.cycleOffset; dest.cycleOffsetParameterActive = source.cycleOffsetParameterActive; dest.iKOnFeet = source.iKOnFeet; dest.mirror = source.mirror; dest.mirrorParameter = source.mirrorParameter; dest.mirrorParameterActive = source.mirrorParameterActive; dest.motion = source.motion; // keep reference dest.speed = source.speed; dest.speedParameter = source.speedParameter; dest.speedParameterActive = source.speedParameterActive; dest.tag = source.tag; dest.timeParameter = source.timeParameter; dest.timeParameterActive = source.timeParameterActive; dest.writeDefaultValues = source.writeDefaultValues; dest.name = source.name; dest.hideFlags = source.hideFlags; foreach (var sourceTransition in source.transitions.Where(w => w.isExit)) { var transition = dest.AddExitTransition(false); sourceTransition.CloneTo(transition); // should always false if (InstanceCaches <AnimatorStateTransition> .Find(sourceTransition.GetInstanceID()) == null) { InstanceCaches <AnimatorStateTransition> .Register(sourceTransition.GetInstanceID(), transition); } } foreach (var sourceTransition in source.transitions.Where(w => !w.isExit)) { AnimatorStateTransition transition = null; if (sourceTransition.destinationStateMachine != null) { transition = dest.AddTransition(InstanceCaches <AnimatorStateMachine> .FindOrCreate(sourceTransition.destinationStateMachine, w => w.CloneDeep())); } if (sourceTransition.destinationState != null) { transition = dest.AddTransition(InstanceCaches <AnimatorState> .FindOrCreate(sourceTransition.destinationState, CloneDeep)); } if (transition == null) { throw new ArgumentNullException(nameof(transition)); } sourceTransition.CloneTo(transition); // should always false if (InstanceCaches <AnimatorStateTransition> .Find(sourceTransition.GetInstanceID()) == null) { InstanceCaches <AnimatorStateTransition> .Register(sourceTransition.GetInstanceID(), transition); } } foreach (var sourceBehaviour in source.behaviours) { var behaviour = dest.AddStateMachineBehaviour(sourceBehaviour.GetType()); sourceBehaviour.CloneDeepTo(behaviour); // store InstanceCaches <StateMachineBehaviour> .Register(behaviour.GetInstanceID(), behaviour); } }
public static void MergeControllers(this AnimatorController source, params AnimatorController[] controllers) { if (string.IsNullOrWhiteSpace(AssetDatabase.GetAssetPath(source))) { throw new InvalidOperationException($"{source} must be persistent at the filesystem"); } var copiedLayers = new List <AnimatorControllerLayer>(); foreach (var controller in controllers) { // deep copy parameters foreach (var parameter in controller.parameters) { if (!source.HasParameter(parameter.name)) { source.AddParameter(parameter.name, parameter.type); } } // deep copy layers if (controller.layers.Length == 0) { return; } var layers = controller.layers; layers.First().defaultWeight = 1.0f; // set a default weight foreach (var layer in layers) { copiedLayers.Add(layer.CloneDeep()); } } if (copiedLayers.Select(w => w.name).Distinct().Count() != copiedLayers.Count) { foreach (var duplicate in copiedLayers.Duplicate(w => w.name)) { var count = 1; var indexes = copiedLayers.Select((w, i) => (Value: w, Index: i)).Where(w => w.Value.name == duplicate).ToList(); foreach (var(layer, _) in indexes) { layer.name = $"{layer.name} - {count++}"; } } } source.layers = copiedLayers.ToArray(); // add instances to controller foreach (var stateMachine in copiedLayers.Select(w => w.stateMachine).Where(w => w != null)) { AssetDatabase.AddObjectToAsset(stateMachine, source); } foreach (var state in InstanceCaches <AnimatorState> .Caches) { AssetDatabase.AddObjectToAsset(state, source); } foreach (var stateMachine in InstanceCaches <AnimatorStateMachine> .Caches) { AssetDatabase.AddObjectToAsset(stateMachine, source); } foreach (var transition in InstanceCaches <AnimatorStateTransition> .Caches) { AssetDatabase.AddObjectToAsset(transition, source); } foreach (var behaviour in InstanceCaches <StateMachineBehaviour> .Caches) { AssetDatabase.AddObjectToAsset(behaviour, source); } // Cleanup All Caches InstanceCaches <AnimatorState> .Clear(); InstanceCaches <AnimatorStateMachine> .Clear(); InstanceCaches <AnimatorStateTransition> .Clear(); InstanceCaches <StateMachineBehaviour> .Clear(); }
public static AnimatorStateMachine CloneDeep(this AnimatorStateMachine source) { var dest = new AnimatorStateMachine { defaultState = InstanceCaches <AnimatorState> .FindOrCreate(source.defaultState, w => w.CloneDeep()), anyStatePosition = source.anyStatePosition, entryPosition = source.entryPosition, exitPosition = source.exitPosition, parentStateMachinePosition = source.parentStateMachinePosition, hideFlags = source.hideFlags, name = source.name }; foreach (var sourceState in source.states) { dest.AddState(InstanceCaches <AnimatorState> .FindOrCreate(sourceState.state, w => w.CloneDeep()), sourceState.position); } foreach (var sourceTransition in source.anyStateTransitions) { AnimatorStateTransition transition = null; if (sourceTransition.destinationStateMachine != null) { transition = dest.AddAnyStateTransition(InstanceCaches <AnimatorStateMachine> .FindOrCreate(sourceTransition.destinationStateMachine, CloneDeep)); } if (sourceTransition.destinationState != null) { transition = dest.AddAnyStateTransition(InstanceCaches <AnimatorState> .FindOrCreate(sourceTransition.destinationState, w => w.CloneDeep())); } if (transition == null) { throw new ArgumentNullException(nameof(transition)); } sourceTransition.CloneTo(transition); // should always false if (InstanceCaches <AnimatorStateTransition> .Find(sourceTransition.GetInstanceID()) == null) { InstanceCaches <AnimatorStateTransition> .Register(sourceTransition.GetInstanceID(), transition); } } foreach (var sourceTransition in source.entryTransitions) { AnimatorTransition transition = null; if (sourceTransition.destinationStateMachine != null) { transition = dest.AddEntryTransition(InstanceCaches <AnimatorStateMachine> .FindOrCreate(sourceTransition.destinationStateMachine, CloneDeep)); } if (sourceTransition.destinationState != null) { transition = dest.AddEntryTransition(InstanceCaches <AnimatorState> .FindOrCreate(sourceTransition.destinationState, w => w.CloneDeep())); } if (transition == null) { throw new ArgumentNullException(nameof(transition)); } transition.CloneTo(sourceTransition); // should always false if (InstanceCaches <AnimatorTransition> .Find(sourceTransition.GetInstanceID()) == null) { InstanceCaches <AnimatorTransition> .Register(sourceTransition.GetInstanceID(), transition); } } foreach (var sourceBehaviour in source.behaviours) { var behaviour = dest.AddStateMachineBehaviour(sourceBehaviour.GetType()); sourceBehaviour.CloneDeepTo(behaviour); // store InstanceCaches <StateMachineBehaviour> .Register(behaviour.GetInstanceID(), behaviour); } foreach (var sourceStateMachine in source.stateMachines) { dest.AddStateMachine(InstanceCaches <AnimatorStateMachine> .FindOrCreate(sourceStateMachine.stateMachine, CloneDeep), sourceStateMachine.position); } return(dest); }