private AnimInfo CreateAnimInfo(AnimationState aState) { AnimInfo animInfo = new AnimInfo(aState); animInfo.currentNormalizedTime = aState.normalizedTime; animInfo.currentWeight = aState.weight; m_animInfoTable.Add(aState, animInfo); return(animInfo); }
public override AnimInfo GetAnim(Worker worker) { if (useGunforPickup && worker.usesMultiTool) { AnimInfo anim = base.GetAnim(worker); anim.smi = new MultitoolController.Instance(this, worker, "pickup", Assets.GetPrefab(EffectConfigs.OreAbsorbId)); return anim; } return base.GetAnim(worker); }
public void ChangeUnitStates(int i, int tar) { string n = UnitStates[tar]; AnimInfo info = Player.Anims.Find(s => { return(s.Name == n); }); if (info != null) { UnitState state = Player.States[i]; Player.UnitStates[state] = info; } }
public int GetUnitStatesIndex(int index) { UnitState state = Player.States[index]; AnimInfo info = Player.UnitStates[state]; if (info != null) { return(UnitStates.FindIndex(s => { return s == info.Name; })); } return(0); }
public AnimInfo Lookup(string animType) { if (string.IsNullOrEmpty(animType)) { return(null); } AnimInfo info = null; AnimInfoList.TryGetValue(animType, out info); return(info); }
/* * Add information about the provided state to the hashtable * */ public void AddAnimInfoToTable(AnimationState aState) { // create the new info object AnimInfo newInfo = new AnimInfo(); // store the current properties newInfo.currentNormalizedTime = aState.normalizedTime; newInfo.currentWeight = aState.weight; // add a new hashtable entry for the AnimInfo animInfoTable.Add(aState, newInfo); }
public void Load(byte[] bytes) { AnimInfoList = new Dictionary <string, AnimInfo>(); BinaryHelper helper = new BinaryHelper(bytes); int listLength = helper.ReadInt(); for (int index = 0; index < listLength; ++index) { AnimInfo info = new AnimInfo(); info.Load(helper); AnimInfoList.Add(info.AnimType, info); } }
public override AnimInfo GetAnim(Worker worker) { AnimInfo result = default(AnimInfo); if (overrideAnims != null && overrideAnims.Length > 0) { result.overrideAnims = overrideAnims; } if (multitoolContext.IsValid && multitoolHitEffectTag.IsValid) { result.smi = new MultitoolController.Instance(this, worker, multitoolContext, Assets.GetPrefab(multitoolHitEffectTag)); } return(result); }
private void Anim_Continue(AnimInfo info) { Mobile from = info.From; IEntity entity = info.Entity; Moongate gate = new Moongate(false); gate.Hue = 0; gate.MoveToWorld(entity.Location, entity.Map); gate.TargetMap = Map.Internal; Timer.DelayCall <Mobile>(TimeSpan.FromSeconds(1.0), new TimerStateCallback <Mobile>(ChangeHide), from); Timer.DelayCall <Moongate>(TimeSpan.FromSeconds(3.0), new TimerStateCallback <Moongate>(KillGate), gate); }
private void Anim_Continue( AnimInfo info ) { Mobile from = info.From; IEntity entity = info.Entity; Moongate gate = new Moongate( false ); if ( m_RedGate ) gate.ItemID = 0xDDA; gate.Hue = m_GateHue > 0 ? m_GateHue : 0; gate.MoveToWorld( entity.Location, entity.Map ); gate.TargetMap = Map.Internal; Timer.DelayCall<Mobile>( TimeSpan.FromSeconds( 1.0 ) , new TimerStateCallback<Mobile>( ChangeHide ), from ); Timer.DelayCall<Moongate>(TimeSpan.FromSeconds( 3.0 ), new TimerStateCallback<Moongate>( KillGate ), gate ); }
public void Play(string name, bool isCrossfade = false) { if (CurAnimName == name) { return; } var idx = animNames.IndexOf(name); if (idx == -1) { UnityEngine.Debug.LogError("miss animation " + name); return; } Debug.Trace($"{owner.EntityId} PlayAnim {name} rawName {CurAnimName}"); var hasChangedAnim = CurAnimName != name; CurAnimName = name; animState = animComp[CurAnimName]; CurAnimInfo = animInfos[idx]; CurAnimBindInfo = config.events.Find((a) => a.name == name); if (CurAnimBindInfo == null) { CurAnimBindInfo = AnimBindInfo.Empty; } if (hasChangedAnim) { //owner.TakeDamage(0, owner.transform2D.Pos3); ResetAnim(); } var state = animComp[CurAnimName]; if (state != null) { if (isCrossfade) { animComp.CrossFade(CurAnimName); } else { animComp.Play(CurAnimName); } } }
public static AnimInfo SetAnimation(this ISkeletonAnimation anim, string nameAnim, bool loop = false, Action onComplete = null, int priority = 0, float speed = 1) { if (animDic.ContainsKey(anim)) { if (animDic[anim].animName == nameAnim) { return(animDic[anim]); } if (animDic[anim].priority <= priority) { animDic[anim] = new AnimInfo(nameAnim, loop, priority); } else { return(animDic[anim]); } } else { animDic.Add(anim, new AnimInfo(nameAnim, loop, priority)); } var animState = (IAnimationStateComponent)(anim); animState.AnimationState.TimeScale = speed; var spine = animState.AnimationState.SetAnimation(1, nameAnim, loop); // animState.AnimationState.SetEmptyAnimations(0); // TrackEntry spine = animState.AnimationState.AddAnimation(1, nameAnim, loop, delay); if (!loop) { spine.Complete += entry => { animDic.Remove(anim); onComplete?.Invoke(); }; } // Debug.LogWarning($"{((SkeletonAnimation) anim).transform.parent.name} " + // $"{((SkeletonAnimation) anim).transform.GetHashCode()} {nameAnim} {loop}", // ((SkeletonAnimation) anim).transform.parent); animDic[anim].duration = spine.Animation.Duration * speed; return(animDic[anim]); }
/// <summary> /// 脚本反射 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="obj"></param> /// <returns></returns> public AnimInfo Reflection(AnimInfo obj) { Type t = obj.GetType(); PropertyInfo[] list = t.GetProperties(); AnimInfo info = new AnimInfo(); Type ti = info.GetType(); for (int i = 0; i < list.Length; i++) { PropertyInfo pt = list[i]; if (pt == null) { continue; } pt.SetValue(info, pt.GetValue(obj, null), null); } return(info); }
//获取切片信息 private static void getClips(string excelPath, ref List <AnimInfo> clips) { Dictionary <int, List <string> > excelMap = new Dictionary <int, List <string> >(); getExcelByPath(excelPath, ref excelMap); //返回的字典key = 2起 foreach (var item in excelMap) { List <string> clipInfo = item.Value; AnimInfo info = new AnimInfo(); info.animName = clipInfo[0].ToString(); info.startIndex = int.Parse(clipInfo[1]); info.endIndex = int.Parse(clipInfo[2]); info.isLoop = int.Parse(clipInfo[3]) == 1; info.speed = clipInfo[4] == null ? 1 : float.Parse(clipInfo[4]); info.nextName = clipInfo.Count <= 5 ? "" : clipInfo[5].ToString(); info.nextExitTime = clipInfo.Count <= 6 ? 0 : float.Parse(clipInfo[6]); info.modelName = clipInfo.Count <= 7 ? "" : clipInfo[7].ToString(); clips.Add(info); } }
/* * Set up further properties for a newly-created info object after calling AddAnimInfoToTable() * */ public void SetupNewAnimInfo(AnimationState aState) { AnimInfo newInfo = (AnimInfo)animInfoTable[aState]; // store information about the animation state up front bool isEnabled = aState.enabled; WrapMode wrapMode = aState.wrapMode; // activate the animation state aState.weight = 1f; aState.enabled = true; aState.wrapMode = WrapMode.Clamp; // ensures the value at normalizedTime = 1f is not necessarily the same as normalizedTime = 0f // scrub to the beginning of the animation state and store initial position and rotation values aState.normalizedTime = 0f; anim.Sample(); newInfo.startPosition = GetProjectedPosition(pelvis); newInfo.previousPosition = GetProjectedPosition(pelvis); newInfo.startAxis = GetProjectedAxis(pelvis, pelvisRightAxis); newInfo.previousAxis = GetProjectedAxis(pelvis, pelvisRightAxis); // scrub to the end of the animation state and store final position and rotation values aState.normalizedTime = 1f; anim.Sample(); newInfo.endPosition = GetProjectedPosition(pelvis); newInfo.endAxis = GetProjectedAxis(pelvis, pelvisRightAxis); // store the total rotation over the course of the animation newInfo.totalRotation = Quaternion.FromToRotation(newInfo.startAxis, newInfo.endAxis); // reset the clip to its starting point and scrub it down to 0 weight aState.normalizedTime = 0f; aState.weight = 0f; aState.enabled = isEnabled; aState.wrapMode = wrapMode; anim.Sample(); animInfoTable[aState] = newInfo; }
public void SetupNewAnimInfo(AnimationState aState) { AnimInfo animInfo = m_animInfoTable[aState]; Boolean enabled = aState.enabled; WrapMode wrapMode = aState.wrapMode; aState.weight = 1f; aState.enabled = true; aState.wrapMode = WrapMode.Once; aState.normalizedTime = 0f; anim.Sample(); animInfo.startAxis = GetProjectedAxis(pelvis, pelvisRightAxis); animInfo.previousAxis = GetProjectedAxis(pelvis, pelvisRightAxis); aState.normalizedTime = 1f; anim.Sample(); animInfo.endAxis = GetProjectedAxis(pelvis, pelvisRightAxis); animInfo.totalRotation = Quaternion.FromToRotation(animInfo.startAxis, animInfo.endAxis); aState.normalizedTime = 0f; aState.weight = 0f; aState.enabled = enabled; aState.wrapMode = wrapMode; anim.Sample(); }
/* * Initialize all necessary variables and warn user as needed * */ public void Initialize() { // validate component references if (anim == null) { anim = gameObject.GetComponentInChildren(typeof(Animation)) as Animation; if (anim == null) Debug.LogError("No animation component has been specified.", this); else if (isDebugMode) Debug.LogWarning(string.Format("No animation component has been specified. Using the animation component on {0}.", gameObject.name), this); } if (rootNode == null) { rootNode = transform; if (isDebugMode) Debug.LogWarning(string.Format("No root object has been manually specified. Assuming that {0} is the root object to be moved.", gameObject.name), this); } if (pelvis == null) { Component[] hierarchy = GetComponentsInChildren(typeof(Transform)); // first try to figure out the pelvis based on name foreach (Transform joint in hierarchy) if (pelvis == null && (joint.name.ToLower() == "hips" || joint.name.ToLower().Contains("pelvis"))) pelvis = joint; // if no named pelvis was found, then try to find the first skinned mesh renderer with children if (pelvis == null) { foreach (Transform joint in hierarchy) { if (joint.GetComponent(typeof(SkinnedMeshRenderer)) == null) continue; Component[] children = joint.GetComponentsInChildren(typeof(Transform)); if (children.Length > 1) pelvis = joint; } } if (pelvis == null) Debug.LogError("No pelvis transform has been specified.", this); else if (isDebugMode) Debug.LogWarning(string.Format("No pelvis object as been manually specified. Assuming that {0} is the pelvis object to track.", pelvis.name)); } // store whether or not the animation component is playing bool isAnimationPlaying = anim.isPlaying; // store information about each AnimationState in a hashtable for easy lookup later animInfoTable = new Hashtable(); // first, figure out what all AnimationStates are currently doing foreach (AnimationState aState in anim) { AddAnimInfoToTable(aState); } anim.Sample(); // BUG: need to call Sample() once up front or AnimationStates in Animation component may reorder during iteration anim.Stop(); // call Stop() to ensure that all weights go to 0 anim.enabled = true; // reenable the animation component to ensure that values will be correct when sampling // store properties for each state one at a time foreach (AnimationState aState in anim) { SetupNewAnimInfo(aState); } // revert the animation component to whatever it was doing beforehand foreach (AnimationState aState in anim) { info = (AnimInfo) animInfoTable[aState]; aState.weight = info.currentWeight; aState.normalizedTime = info.currentNormalizedTime; } if (isAnimationPlaying) anim.Play(); else anim.Stop(); initialized = true; }
public static string ToXml(BFLAN.Header header) { XmlRoot root = new XmlRoot(); root.head = new Head(); root.body = new Body(); var generator = new Generator(); root.head.generator = generator; generator.name = "ST"; generator.version = "1.0" ; var create = new Create(); root.head.create = create; create.date = DateTime.Now.ToString("yyyy-MM-ddThh:mm:ss"); BinaryInfo info = new BinaryInfo(); info.layout.name = header.AnimationTag.Name; info.version.major = (byte)header.VersionMajor; info.version.minor = (byte)header.VersionMinor; info.version.micro = (byte)header.VersionMicro; info.version.micro2 = (byte)header.VersionMicro2; root.head.binaryInfo = info; AnimTag tag = new AnimTag(); AnimInfo animInfo = new AnimInfo(); if (header.AnimationInfo.Loop) { tag.animLoop = AnimLoopType.Loop; } tag.descendingBind = header.AnimationTag.ChildBinding; tag.name = header.AnimationTag.Name; tag.fileName = header.AnimationTag.Name; tag.startFrame = header.AnimationTag.StartFrame; tag.endFrame = header.AnimationTag.EndFrame; tag.group = new Group[header.AnimationTag.Groups.Count]; for (int i = 0; i < header.AnimationTag.Groups.Count; i++) { tag.group[i] = new Group(); tag.group[i].name = header.AnimationTag.Groups[i]; } root.body.animTag[0] = tag; root.body.lan[0] = animInfo; var bflanInfo = header.AnimationInfo; var animContent = new AnimContent(); animInfo.animContent = new AnimContent[1]; animInfo.animContent[0] = animContent; animInfo.startFrame = bflanInfo.FrameSize; XmlWriterSettings settings = new XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true, IndentChars = " ", }; XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", ""); XmlDocument doc = new XmlDocument(); XmlDeclaration xmldecl = doc.CreateXmlDeclaration("1.0", null, null); xmldecl.Encoding = "UTF-8"; xmldecl.Standalone = "yes"; var stringWriter = new StringWriter(); XmlSerializer serializer = new XmlSerializer(typeof(XmlRoot)); XmlWriter output = XmlWriter.Create(stringWriter, settings); serializer.Serialize(output, root, ns); return(stringWriter.ToString()); }
/* * Compute the root motion variables * */ public void ComputeRootMotion() { // early out if no animation is playing if (!anim.isPlaying) return; // store whether or not we should be bothering to compute rotation parameters bool isRotationMode = (computationMode == RootMotionComputationMode.TranslationAndRotation); // an array to store any AnimationStates that have been added to the animation component since the last frame ArrayList newlyAddedAnimationStates = null; // first store current actual weight and time information for all AnimationStates foreach (AnimationState aState in anim) { // store the highest and lowest layers for use in a later iteration if (aState.layer > highestLayer) highestLayer = aState.layer; if (aState.layer < lowestLayer) lowestLayer = aState.layer; // if any new animation states have been added, then deal with them in a following iteration if (!animInfoTable.ContainsKey(aState)) { AddAnimInfoToTable(aState); newlyAddedAnimationStates.Add(aState); continue; } info = (AnimInfo) animInfoTable[aState]; info.currentNormalizedTime = aState.normalizedTime; info.currentWeight = aState.weight; animInfoTable[aState] = info; // scrub the weight down to 0 for the next iteration aState.weight = 0f; } // if any new AnimationStates have been added, add their info to the table if (newlyAddedAnimationStates != null && newlyAddedAnimationStates.Count > 0) { // first set all weights to 0, which will include newly added states foreach (AnimationState aState in anim) aState.weight = 0f; // store all the properties for the new states foreach (AnimationState aState in newlyAddedAnimationStates) SetupNewAnimInfo(aState); } // compute normalized AnimationState weights across layers since Unity does not expose them float remainingWeight = 1f; for (int i=highestLayer; i>=lowestLayer; i--) { if (remainingWeight <= 0f) continue; float weightOnThisLayer = 0f; foreach (AnimationState aState in anim) { if (aState.layer != i) continue; info = (AnimInfo) animInfoTable[aState]; // find out how much weight the animation state is actually contributing this frame info.contributingWeight = remainingWeight * info.currentWeight; weightOnThisLayer += info.contributingWeight; animInfoTable[aState] = info; } // if the weight on this layer is > 1, then normalize it // using Blend() or setting weights manually will not affect other weights on the layer, so they must be manually renormalized if (weightOnThisLayer > 1f) { float oneOverWeightOnThisLayer = 1f/weightOnThisLayer; foreach (AnimationState aState in anim) { if (aState.layer != i) continue; info = (AnimInfo) animInfoTable[aState]; info.contributingWeight = info.contributingWeight * oneOverWeightOnThisLayer; animInfoTable[aState] = info; } weightOnThisLayer = 1f; } remainingWeight -= weightOnThisLayer; } // reset the delta values for this frame dPosition = Vector3.zero; dRotation = Quaternion.identity; // compute each AnimationState's individual contribution to the current frame's delta values foreach (AnimationState aState in anim) { info = (AnimInfo) animInfoTable[aState]; // early out if this state was contributing nothing this frame if (info.contributingWeight == 0f) continue; // early out if aState uses additive blending // NOTE: Not entirely sure if this is ideal or not, but it generally should be if (aState.blendMode == AnimationBlendMode.Additive) continue; // scrub the weight up to 1 for sampling values aState.weight = 1f; // sample the values for the projected root configuration back one frame // NOTE: cannot simply store these values from one frame to the next since user may manually change the time value at any point aState.time = aState.time - Time.deltaTime * aState.speed; info.previousNormalizedTime = aState.normalizedTime; anim.Sample(); info.previousAxis = GetProjectedAxis(pelvis, pelvisRightAxis); info.previousPosition = GetProjectedPosition(pelvis); // sample the values for the projected root configuration at the current frame aState.normalizedTime = info.currentNormalizedTime; anim.Sample(); info.currentPosition = GetProjectedPosition(pelvis); info.currentAxis = GetProjectedAxis(pelvis, pelvisRightAxis); // ensure both normalizedTime values are positive info.previousNormalizedTime = 1f + info.previousNormalizedTime - (int)info.previousNormalizedTime; info.currentNormalizedTime = 1f + info.currentNormalizedTime - (int)info.currentNormalizedTime; // determine the contribution to the root's delta this frame based on whether the animation looped since the previous frame if (info.previousNormalizedTime-(int)info.previousNormalizedTime > info.currentNormalizedTime-(int)info.currentNormalizedTime) { // compute displacement with respect to identity p = info.contributingWeight * ((info.endPosition - info.previousPosition) + (info.currentPosition - info.startPosition)); if (isRotationMode) { // rotate displacement into current orientation p = Quaternion.FromToRotation(info.currentAxis, info.totalRotation*Vector3.right) * p; // compute angular displacement and append to result dRotation *= Quaternion.Slerp(Quaternion.identity, Quaternion.FromToRotation(info.previousAxis, info.endAxis) * Quaternion.FromToRotation(info.startAxis, info.currentAxis), info.contributingWeight); } // append displacement to result dPosition += p; } else { // compute displacement with respect to identity p = info.contributingWeight * (info.currentPosition - info.previousPosition); if (isRotationMode) { // rotate displacement into current orientation p = Quaternion.FromToRotation(info.currentAxis, Vector3.right) * p; // compute angular displacement and append to result dRotation *= Quaternion.Slerp(Quaternion.identity, Quaternion.FromToRotation(info.previousAxis, info.currentAxis), info.contributingWeight); } // append displacement to result dPosition += p; } // scrub the weight back down to 0 so as to not affect sampling of other states aState.weight = 0f; } // reset weights to where they were before computation foreach (AnimationState aState in anim) { info = (AnimInfo) animInfoTable[aState]; aState.weight = info.currentWeight; } // return the character to its current pose anim.Sample(); // delta values for the first frame should simply move from the starting configuration into the current frame of animation if (isFirstFrame) { // simply translate and rotate to the current projected position and orientation dPosition = GetProjectedPosition(pelvis); dRotation = Quaternion.FromToRotation(Vector3.right, GetProjectedAxis(pelvis, pelvisRightAxis)); // rotate displacement into current orientation if (isRotationMode) dPosition = Quaternion.FromToRotation(GetProjectedAxis(pelvis, pelvisRightAxis), Vector3.right) * dPosition; isFirstFrame = false; } // store the local position of the pelvis before returning it to hover over the root pLocalPosition = pelvis.localPosition; // zero out the local x-component of the position delta if root translation method is z-only if (computationMode == RootMotionComputationMode.ZTranslation) dPosition = Vector3.forward * Vector3.Dot(dPosition, Vector3.forward); // otherwise zero out the local x-position of the pelvis else pLocalPosition.x = 0f; // return the pelvis to a point hovering over the root pLocalPosition.z = 0f; pelvis.localPosition = pLocalPosition; // if computing rotation, then zero out local y-rotation of the pelvis if (isRotationMode) pelvis.localRotation = Quaternion.FromToRotation(GetProjectedAxis(pelvis, pelvisRightAxis), Vector3.right) * pelvis.localRotation; // draw debug lines if requested if (isDebugMode) DrawDebug(); // return if root movement is not requested (e.g. a character controller will use delta values) if (!applyMotion) return; /* @beacco */ // ADDED THIS CONDITION TO AVOID THE "SUDDEN TRANSLATION BACKWARDS" WHEN PLAYING AT DIFFERENT SPEEDS if (dPosition.sqrMagnitude < 0.001f) { // apply rotation if requested if (isRotationMode) rootNode.localRotation *= dRotation; // apply translation rootNode.Translate(dPosition*scale, Space.Self); } }
/* * Compute the root motion variables * */ public void ComputeRootMotion() { // early out if no animation is playing if (!anim.isPlaying) { return; } // store whether or not we should be bothering to compute rotation parameters bool isRotationMode = (computationMode == RootMotionComputationMode.TranslationAndRotation); // an array to store any AnimationStates that have been added to the animation component since the last frame ArrayList newlyAddedAnimationStates = null; // first store current actual weight and time information for all AnimationStates foreach (AnimationState aState in anim) { // store the highest and lowest layers for use in a later iteration highestLayer = Mathf.Max(highestLayer, aState.layer); lowestLayer = Mathf.Min(lowestLayer, aState.layer); // if any new animation states have been added, then deal with them in a following iteration if (!animInfoTable.ContainsKey(aState)) { AddAnimInfoToTable(aState); newlyAddedAnimationStates.Add(aState); continue; } info = (AnimInfo)animInfoTable[aState]; info.currentNormalizedTime = aState.normalizedTime; info.currentWeight = aState.weight; animInfoTable[aState] = info; // scrub the weight down to 0 for the next iteration aState.weight = 0f; } // if any new AnimationStates have been added, add their info to the table if (newlyAddedAnimationStates != null && newlyAddedAnimationStates.Count > 0) { // first set all weights to 0, which will include newly added states foreach (AnimationState aState in anim) { aState.weight = 0f; } // store all the properties for the new states foreach (AnimationState aState in newlyAddedAnimationStates) { SetupNewAnimInfo(aState); } } // compute normalized AnimationState weights across layers since Unity does not expose them float remainingWeight = 1f; for (int i = highestLayer; i >= lowestLayer; i--) { float weightOnThisLayer = 0f; foreach (AnimationState aState in anim) { if (aState.layer != i) { continue; } info = (AnimInfo)animInfoTable[aState]; // find out how much weight the animation state is actually contributing this frame if (!aState.enabled || remainingWeight <= 0f) { info.contributingWeight = 0f; } else { info.contributingWeight = remainingWeight * info.currentWeight; } weightOnThisLayer += info.contributingWeight; animInfoTable[aState] = info; } // if the weight on this layer is > 1, then normalize it // using Blend() or setting weights manually will not affect other weights on the layer, so they must be manually renormalized if (weightOnThisLayer > 1f) { float oneOverWeightOnThisLayer = 1f / weightOnThisLayer; foreach (AnimationState aState in anim) { if (aState.layer != i) { continue; } info = (AnimInfo)animInfoTable[aState]; info.contributingWeight = info.contributingWeight * oneOverWeightOnThisLayer; animInfoTable[aState] = info; } weightOnThisLayer = 1f; } remainingWeight -= weightOnThisLayer; } // reset the delta values for this frame dPosition = Vector3.zero; dRotation = Quaternion.identity; // compute each AnimationState's individual contribution to the current frame's delta values foreach (AnimationState aState in anim) { info = (AnimInfo)animInfoTable[aState]; // early out if this state was contributing nothing this frame if (info.contributingWeight == 0f) { continue; } // early out if aState uses additive blending // NOTE: Not entirely sure if this is ideal or not, but it generally should be if (aState.blendMode == AnimationBlendMode.Additive) { continue; } // scrub the weight up to 1 for sampling values aState.weight = 1f; // sample the values for the projected root configuration back one frame // NOTE: cannot simply store these values from one frame to the next since user may manually change the time value at any point aState.time = aState.time - Time.deltaTime * aState.speed; info.previousNormalizedTime = aState.normalizedTime; anim.Sample(); info.previousAxis = GetProjectedAxis(pelvis, pelvisRightAxis); info.previousPosition = GetProjectedPosition(pelvis); // sample the values for the projected root configuration at the current frame aState.normalizedTime = info.currentNormalizedTime; anim.Sample(); info.currentPosition = GetProjectedPosition(pelvis); info.currentAxis = GetProjectedAxis(pelvis, pelvisRightAxis); // ensure both normalizedTime values are positive info.previousNormalizedTime = 1f + info.previousNormalizedTime - (int)info.previousNormalizedTime; info.currentNormalizedTime = 1f + info.currentNormalizedTime - (int)info.currentNormalizedTime; // determine the contribution to the root's delta this frame based on whether the animation looped since the previous frame if (info.previousNormalizedTime - (int)info.previousNormalizedTime > info.currentNormalizedTime - (int)info.currentNormalizedTime) { // compute displacement with respect to identity p = info.contributingWeight * ((info.endPosition - info.previousPosition) + (info.currentPosition - info.startPosition)); if (isRotationMode) { // rotate displacement into current orientation p = Quaternion.FromToRotation(info.currentAxis, info.totalRotation * Vector3.right) * p; // compute angular displacement and append to result dRotation *= Quaternion.Slerp(Quaternion.identity, Quaternion.FromToRotation(info.previousAxis, info.endAxis) * Quaternion.FromToRotation(info.startAxis, info.currentAxis), info.contributingWeight); } // append displacement to result dPosition += p; } else { // compute displacement with respect to identity p = info.contributingWeight * (info.currentPosition - info.previousPosition); if (isRotationMode) { // rotate displacement into current orientation p = Quaternion.FromToRotation(info.currentAxis, Vector3.right) * p; // compute angular displacement and append to result dRotation *= Quaternion.Slerp(Quaternion.identity, Quaternion.FromToRotation(info.previousAxis, info.currentAxis), info.contributingWeight); } // append displacement to result dPosition += p; } // scrub the weight back down to 0 so as to not affect sampling of other states aState.weight = 0f; } // reset weights to where they were before computation foreach (AnimationState aState in anim) { info = (AnimInfo)animInfoTable[aState]; aState.weight = info.currentWeight; } // return the character to its current pose anim.Sample(); // delta values for the first frame should simply move from the starting configuration into the current frame of animation if (isFirstFrame) { // simply translate and rotate to the current projected position and orientation dPosition = GetProjectedPosition(pelvis); dRotation = Quaternion.FromToRotation(Vector3.right, GetProjectedAxis(pelvis, pelvisRightAxis)); // rotate displacement into current orientation if (isRotationMode) { dPosition = Quaternion.FromToRotation(GetProjectedAxis(pelvis, pelvisRightAxis), Vector3.right) * dPosition; } isFirstFrame = false; } // store the local position of the pelvis before returning it to hover over the root pLocalPosition = pelvis.localPosition; // zero out the local x-component of the position delta if root translation method is z-only if (computationMode == RootMotionComputationMode.ZTranslation) { dPosition = Vector3.forward * Vector3.Dot(dPosition, Vector3.forward); } // otherwise zero out the local x-position of the pelvis else { pLocalPosition.x = 0f; } // return the pelvis to a point hovering over the root pLocalPosition.z = 0f; pelvis.localPosition = pLocalPosition; // if computing rotation, then zero out local y-rotation of the pelvis if (isRotationMode) { pelvis.localRotation = Quaternion.FromToRotation(GetProjectedAxis(pelvis, pelvisRightAxis), Vector3.right) * pelvis.localRotation; } // draw debug lines if requested if (isDebugMode) { DrawDebug(); } // return if root movement is not requested (e.g. a character controller will use delta values) if (!applyMotion) { return; } // apply rotation if requested if (isRotationMode) { rootNode.localRotation *= dRotation; } // apply translation rootNode.Translate(dPosition, Space.Self); }
public override void OnInspectorGUI() { anim = (AnimInfo)target; base.OnInspectorGUI(); //EditorGUILayout.PropertyField(anim); //EditorGUILayout.LabelField("abcd"); if (anim.clip != null) { EditorGUILayout.LabelField("frameRate:" + anim.clip.frameRate + " ,length:" + anim.clip.length); pos0 = EditorGUILayout.BeginScrollView(pos0, GUILayout.Height(200)); foreach (var binding in AnimationUtility.GetCurveBindings(anim.clip)) { AnimationCurve curve = AnimationUtility.GetEditorCurve(anim.clip, binding); string s = string.Format("{0}({1}):{2}, KeyLen:{3}", binding.path, binding.GetHashCode(), binding.propertyName, curve.keys.Length); if (!animMap.ContainsKey(binding.path)) { animMap.Add(binding.path, new Sampler(binding.path, anim.clip.frameRate, anim.clip.length)); } animMap[binding.path].addCurve(binding.propertyName, curve); /* * if(binding.propertyName == "m_LocalPosition.x") * { * calcCurve(curve, anim.clip.frameRate, anim.clip.length); * } */ //EditorGUILayout.LabelField( binding.propertyName + ", Keys: " + curve.keys.Length); EditorGUILayout.LabelField(s); } foreach (var kv in animMap) { kv.Value.finish(); } EditorGUILayout.EndScrollView(); } EditorGUILayout.Separator(); if (anim.obj != null) { var smr = anim.obj.GetComponentInChildren <SkinnedMeshRenderer>(); var bones = smr.bones; var root = smr.rootBone; pos = EditorGUILayout.BeginScrollView(pos); for (int idx = 0; idx < bones.Length; idx++) { string s = string.Format("{0}->({7}).pos[{1},{2},{3}], localPos[{4},{5},{6}]", bones[idx].name, bones[idx].position.x, bones[idx].position.y, bones[idx].position.z, bones[idx].localPosition.x, bones[idx].localPosition.y, bones[idx].localPosition.z, bones[idx].name.GetHashCode()); EditorGUILayout.LabelField(s); } EditorGUILayout.EndScrollView(); } }
static IEnumerator GenThings(Object selector) { var path = AssetDatabase.GetAssetPath(selector); var dir = "Assets/Prefab"; var originPrefab = (GameObject)GameObject.Instantiate(selector); originPrefab.name = selector.name; var animator = originPrefab.GetComponent <Animator>(); if (animator == null) { GameObject.DestroyImmediate(originPrefab); Debug.LogError("selection prefab does not have Animator component!"); yield break; } var skin = originPrefab.GetComponentInChildren <SkinnedMeshRenderer>(); var modelMesh = new Mesh(); skin.BakeMesh(modelMesh); var uvs = new Vector2[modelMesh.vertices.Length]; for (int k = 0; k < modelMesh.vertices.Length; k++) { uvs[k] = new Vector2(k, 0.0f); } modelMesh.uv3 = uvs; var folderName = "GPU"; var parentFolder = Path.Combine(dir, folderName); // Assets/Prefab/GPU var subFolder = Path.Combine(parentFolder, originPrefab.name); // Assets/Prefab/GPU/name if (Directory.Exists(subFolder)) { FileUtil.DeleteFileOrDirectory(subFolder); AssetDatabase.Refresh(); } AssetDatabase.CreateFolder(parentFolder, originPrefab.name); var savePath = Path.Combine(subFolder, string.Format("{0}_mesh.asset", originPrefab.name)); AssetDatabase.CreateAsset(modelMesh, savePath); //保存mesh var vCount = skin.sharedMesh.vertexCount; var texWidth = vCount; var totalFrame = 0; UnityEditor.Animations.AnimatorController animatorController = (UnityEditor.Animations.AnimatorController)animator.runtimeAnimatorController; UnityEditor.Animations.AnimatorStateMachine stateMachine = animatorController.layers[0].stateMachine; for (int i = 0; i < stateMachine.states.Length; i++) { AnimationClip clip = stateMachine.states[i].state.motion as AnimationClip; totalFrame += (int)(clip.length / SampleFactor) + 1; } var defaultState = stateMachine.defaultState; Texture2D posTex = new Texture2D(texWidth, totalFrame, TextureFormat.RGBAHalf, false); posTex.wrapMode = TextureWrapMode.Clamp; posTex.filterMode = FilterMode.Point; animator.speed = 0; //因为靠代码手动Update,所以speed设置为0. float boundMin = 0; float boundMax = 0; int frameOffset = 0; List <AnimInfo> animInfos = new List <AnimInfo>(); List <List <Color> > pixels = new List <List <Color> >(); for (int i = 0; i < stateMachine.states.Length; i++) { UnityEditor.Animations.AnimatorState state = stateMachine.states[i].state; AnimationClip clip = state.motion as AnimationClip; var thisClipFrames = (int)(clip.length / SampleFactor) + 1; animator.Play(state.name); for (int j = 0; j < thisClipFrames; j++) { List <Color> pos = new List <Color>(); animator.Play(state.name, 0, (float)j / thisClipFrames); animator.Update(Time.deltaTime); yield return(null); skin.BakeMesh(modelMesh); for (int z = 0; z < modelMesh.vertexCount; z++) { Vector3 vertex = modelMesh.vertices[z]; Color col = new Color(vertex.x, vertex.y, vertex.z); pos.Add(col); boundMin = Mathf.Min(boundMin, vertex.x, vertex.y, vertex.z); boundMax = Mathf.Max(boundMax, vertex.x, vertex.y, vertex.z); } pixels.Add(pos); } AnimInfo info = new AnimInfo(); info.animFrameOffset = frameOffset; info.totalFrames = totalFrame; info.animFrameNum = thisClipFrames; info.m_boundMax = boundMax; info.m_boundMin = boundMin; info.animLen = clip.length; info.animName = state.name; info.loop = clip.isLooping; info.isDefault = (state == defaultState); animInfos.Add(info); frameOffset += thisClipFrames; } var diff = boundMax - boundMin; for (int i = 0; i < pixels.Count; i++) { var item = pixels[i]; for (int j = 0; j < item.Count; j++) { var pixel = item[j]; pixel.r = (pixel.r - boundMin) / diff; pixel.g = (pixel.g - boundMin) / diff; pixel.b = (pixel.b - boundMin) / diff; posTex.SetPixel(j, i, pixel); } } posTex.Apply(); AssetDatabase.CreateAsset(posTex, Path.Combine(subFolder, string.Format("{0}_pos.asset", originPrefab.name))); //保存位置纹理 File.WriteAllBytes(Path.Combine(subFolder, string.Format("{0}_pos.png", originPrefab.name)), posTex.EncodeToPNG()); Shader shader = Shader.Find("Custom/GPUAnimation"); Material mat = new Material(shader); for (int i = 0; i < animInfos.Count; i++) { if (animInfos[i].isDefault) { mat.SetFloat("_BoundMax", animInfos[i].m_boundMax); mat.SetFloat("_BoundMin", animInfos[i].m_boundMin); mat.SetTexture("_PosTex", posTex); } } mat.enableInstancing = true; AssetDatabase.CreateAsset(mat, Path.Combine(subFolder, string.Format("{0}_mat.mat", originPrefab.name))); //保存材质 GameObject newPrefab = new GameObject(originPrefab.name); GameObject model = new GameObject("model"); model.transform.parent = newPrefab.transform; model.transform.localScale = Vector3.one; model.transform.localPosition = Vector3.zero; model.transform.localEulerAngles = Vector3.zero; model.AddComponent <MeshFilter>().sharedMesh = modelMesh; model.AddComponent <MeshRenderer>().sharedMaterial = mat; PrefabUtility.SaveAsPrefabAsset(newPrefab, Path.Combine(subFolder, string.Format("{0}_prefab.prefab", originPrefab.name))); GameObject.DestroyImmediate(originPrefab); GameObject.DestroyImmediate(newPrefab); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); }
//协程-加载模型,并播放standby动画 IEnumerator Coroutine_LoadModel(string prefabName, int modelID, int weaponID, GameObject parentObj, GameResPackage.AsyncLoadObjectData data, bool isAutoActive = true) { IEnumerator e = PoolManager.Singleton.Coroutine_Load(prefabName, data, true); while (true) { e.MoveNext(); if (data.m_isFinish) { break; } yield return(e.Current); } if (null != data.m_obj) { GameObject obj = data.m_obj as GameObject; obj.layer = GameObject.Find("UI Root (2D)").layer; obj.SetActive(true); foreach (Transform t in obj.transform.GetComponentsInChildren <Transform>()) { t.gameObject.layer = obj.layer; } PreAnimationLoad.Singleton.LoadAnimation(obj, modelID, weaponID); Animation MainAnim = obj.GetComponent <Animation>(); if (null != MainAnim) { string mAnimName = ""; ModelInfo info = GameTable.ModelInfoTableAsset.Lookup(modelID); WeaponInfo wInfo = GameTable.WeaponInfoTableAsset.Lookup(weaponID); if (info != null && wInfo != null) { mAnimName = "a-" + info.modelType.ToString() + "-w" + ((int)wInfo.WeaponType).ToString() + "-"; } AnimInfo tempAnimData = GameTable.AnimationTableAsset.Lookup("standby"); if (null != tempAnimData) { mAnimName = mAnimName + tempAnimData.AnimName[UnityEngine.Random.Range(0, tempAnimData.AnimName.Length)]; } AnimationClip clip = MainAnim.GetClip(mAnimName); if (clip != null) { MainAnim.CrossFade(clip.name); } else { Debug.LogWarning("play model animation fail,prefabName:" + prefabName + ",animationName:" + mAnimName); } } obj.transform.parent = parentObj.transform; obj.transform.localPosition = Vector3.zero; obj.transform.localScale = Vector3.one; obj.transform.localRotation = Quaternion.Euler(0, 0, 0); if (weaponID != 0) { GameResPackage.AsyncLoadPackageData data2 = new GameResPackage.AsyncLoadPackageData(); IEnumerator e2 = Coroutine_LoadWeapon(obj, weaponID, data2); while (true) { e2.MoveNext(); if (data2.m_isFinish) { break; } yield return(e2.Current); } } obj.SetActive(isAutoActive); } }
/* * Initialize all necessary variables and warn user as needed * */ public void Initialize() { // validate component references if (anim == null) { anim = gameObject.GetComponentInChildren(typeof(Animation)) as Animation; // if (anim == null) Debug.LogError("No animation component has been specified.", this); // else if (isDebugMode) Debug.LogWarning(string.Format("No animation component has been specified. Using the animation component on {0}.", gameObject.name), this); } if (rootNode == null) { rootNode = transform; // if (isDebugMode) Debug.LogWarning(string.Format("No root object has been manually specified. Assuming that {0} is the root object to be moved.", gameObject.name), this); } if (pelvis == null) { Component[] hierarchy = GetComponentsInChildren(typeof(Transform)); // first try to figure out the pelvis based on name foreach (Transform joint in hierarchy) { if (pelvis == null && (joint.name.ToLower() == "hips" || joint.name.ToLower().Contains("pelvis"))) { pelvis = joint; } } // if no named pelvis was found, then try to find the first skinned mesh renderer with children if (pelvis == null) { foreach (Transform joint in hierarchy) { if (joint.GetComponent(typeof(SkinnedMeshRenderer)) == null) { continue; } Component[] children = joint.GetComponentsInChildren(typeof(Transform)); if (children.Length > 1) { pelvis = joint; } } } // if (pelvis == null) Debug.LogError("No pelvis transform has been specified.", this); // else if (isDebugMode) Debug.LogWarning(string.Format("No pelvis object has been manually specified. Assuming that {0} is the pelvis object to track.", pelvis.name)); } // store whether or not the animation component is playing bool isAnimationPlaying = anim.isPlaying; // store information about each AnimationState in a hashtable for easy lookup later animInfoTable = new Hashtable(); // first, figure out what all AnimationStates are currently doing foreach (AnimationState aState in anim) { AddAnimInfoToTable(aState); } anim.Sample(); // BUG: need to call Sample() once up front or AnimationStates in Animation component may reorder during iteration anim.Stop(); // call Stop() to ensure that all weights go to 0 anim.enabled = true; // reenable the animation component to ensure that values will be correct when sampling // store properties for each state one at a time foreach (AnimationState aState in anim) { SetupNewAnimInfo(aState); } // revert the animation component to whatever it was doing beforehand foreach (AnimationState aState in anim) { info = (AnimInfo)animInfoTable[aState]; aState.weight = info.currentWeight; aState.normalizedTime = info.currentNormalizedTime; } if (isAnimationPlaying) { anim.Play(); } else { anim.Stop(); } }
public void Initialize() { if (anim == null) { anim = gameObject.GetComponentInChildren <Animation>(); if (anim == null) { Debug.LogError("No animation component has been specified.", this); } else if (isDebugMode) { Debug.LogWarning(String.Format("No animation component has been specified. Using the animation component on {0}.", gameObject.name), this); } } if (rootNode == null) { rootNode = transform; if (isDebugMode) { Debug.LogWarning(String.Format("No root object has been manually specified. Assuming that {0} is the root object to be moved.", gameObject.name), this); } } if (pelvis == null) { Transform[] componentsInChildren = GetComponentsInChildren <Transform>(); foreach (Transform transform in componentsInChildren) { if (pelvis == null && (transform.name.ToLower() == "hips" || transform.name.ToLower().Contains("pelvis"))) { pelvis = transform; } } if (pelvis == null) { foreach (Transform transform2 in componentsInChildren) { if (!(transform2.GetComponent <SkinnedMeshRenderer>() == null)) { Transform[] componentsInChildren2 = transform2.GetComponentsInChildren <Transform>(); if (componentsInChildren2.Length > 1) { pelvis = transform2; } } } } if (pelvis == null) { Debug.LogError("No pelvis transform has been specified.", this); } else if (isDebugMode) { Debug.LogWarning(String.Format("No pelvis object as been manually specified. Assuming that {0} is the pelvis object to track.", pelvis.name)); } } Boolean isPlaying = anim.isPlaying; m_animInfoTable.Clear(); IEnumerator enumerator = anim.GetEnumerator(); try { while (enumerator.MoveNext()) { Object obj = enumerator.Current; AnimationState aState = (AnimationState)obj; AddAnimInfoToTable(aState); } } finally { IDisposable disposable; if ((disposable = (enumerator as IDisposable)) != null) { disposable.Dispose(); } } anim.Sample(); anim.Stop(); anim.enabled = true; IEnumerator enumerator2 = anim.GetEnumerator(); try { while (enumerator2.MoveNext()) { Object obj2 = enumerator2.Current; AnimationState aState2 = (AnimationState)obj2; SetupNewAnimInfo(aState2); } } finally { IDisposable disposable2; if ((disposable2 = (enumerator2 as IDisposable)) != null) { disposable2.Dispose(); } } IEnumerator enumerator3 = anim.GetEnumerator(); try { while (enumerator3.MoveNext()) { Object obj3 = enumerator3.Current; AnimationState animationState = (AnimationState)obj3; AnimInfo animInfo = m_animInfoTable[animationState]; animationState.weight = animInfo.currentWeight; animationState.normalizedTime = animInfo.currentNormalizedTime; } } finally { IDisposable disposable3; if ((disposable3 = (enumerator3 as IDisposable)) != null) { disposable3.Dispose(); } } if (isPlaying) { anim.Play(); } else { anim.Stop(); } }
public void ComputeRootMotion() { if (!anim.isPlaying) { return; } Boolean flag = computationMode == RootMotionComputationMode.TranslationAndRotation; Int32 num = LoadAnimInfos(anim, ref m_AnimInfos); AnimInfo[] animInfos = m_AnimInfos; Int32 num2 = 0; while (num2 < animInfos.Length && num2 < num) { AnimInfo animInfo = animInfos[num2]; animInfo.currentNormalizedTime = animInfo.AnimState.normalizedTime; animInfo.currentWeight = animInfo.AnimState.weight; animInfo.AnimState.weight = 0f; num2++; } Array.Sort <AnimInfo>(animInfos, 0, num, StateLayerSort.Default); Single num3 = 1f; Int32 num4 = 0; while (num4 < animInfos.Length && num4 < num) { Int32 layer = animInfos[num4].layer; Single num5 = 0f; Int32 num6 = 0; while (num6 < animInfos.Length && num6 < num) { AnimInfo animInfo = animInfos[num6]; if (animInfo.layer == layer) { if (!animInfo.AnimState.enabled || num3 <= 0f) { animInfo.contributingWeight = 0f; } else { animInfo.contributingWeight = num3 * animInfo.currentWeight; } num5 += animInfo.contributingWeight; } num6++; } if (num5 > 1f) { Single num7 = 1f / num5; Int32 num8 = 0; while (num8 < animInfos.Length && num8 < num) { AnimInfo animInfo = animInfos[num8]; if (animInfo.layer == layer) { animInfo.contributingWeight *= num7; } num8++; } num5 = 1f; } num3 -= num5; num4++; } dRotation = Quaternion.identity; Int32 num9 = 0; while (num9 < animInfos.Length && num9 < num) { AnimInfo animInfo = animInfos[num9]; if (animInfo.contributingWeight != 0f) { if (animInfo.AnimState.blendMode != AnimationBlendMode.Additive) { animInfo.AnimState.weight = 1f; animInfo.AnimState.time -= Time.deltaTime * animInfo.AnimState.speed; animInfo.previousNormalizedTime = animInfo.AnimState.normalizedTime; anim.Sample(); animInfo.previousAxis = GetProjectedAxis(pelvis, pelvisRightAxis); animInfo.AnimState.normalizedTime = animInfo.currentNormalizedTime; anim.Sample(); animInfo.currentAxis = GetProjectedAxis(pelvis, pelvisRightAxis); Single num10 = animInfo.previousNormalizedTime - (Int32)animInfo.previousNormalizedTime; Single num11 = animInfo.currentNormalizedTime - (Int32)animInfo.currentNormalizedTime; animInfo.previousNormalizedTime = 1f + num10; animInfo.currentNormalizedTime = 1f + num11; if (num10 > num11) { if (flag) { dRotation *= Quaternion.Slerp(Quaternion.identity, Quaternion.FromToRotation(animInfo.previousAxis, animInfo.endAxis) * Quaternion.FromToRotation(animInfo.startAxis, animInfo.currentAxis), animInfo.contributingWeight); } } else if (flag) { dRotation *= Quaternion.Slerp(Quaternion.identity, Quaternion.FromToRotation(animInfo.previousAxis, animInfo.currentAxis), animInfo.contributingWeight); } animInfo.AnimState.weight = 0f; } } num9++; } Int32 num12 = 0; while (num12 < animInfos.Length && num12 < num) { AnimInfo animInfo = animInfos[num12]; animInfo.AnimState.weight = animInfo.currentWeight; num12++; } anim.Sample(); if (isFirstFrame) { dRotation = Quaternion.FromToRotation(Vector3.right, GetProjectedAxis(pelvis, pelvisRightAxis)); isFirstFrame = false; } if (flag) { Quaternion lhs = Quaternion.FromToRotation(GetProjectedAxis(pelvis, pelvisRightAxis), Vector3.right); for (Int32 i = 0; i < rootBones.Length; i++) { rootBones[i].localRotation = lhs * rootBones[i].localRotation; } } if (!applyMotion) { return; } if (flag) { rootNode.localRotation *= dRotation; } }