导入角色动画,和增加角色控制
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
namespace KINEMATION.KAnimationCore.Runtime.Rig
|
||||
{
|
||||
public interface IRigObserver
|
||||
{
|
||||
public void OnRigUpdated();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00acdb04eae148a0b993a37cb2b95007
|
||||
timeCreated: 1708431186
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace KINEMATION.KAnimationCore.Runtime.Rig
|
||||
{
|
||||
public interface IRigProvider
|
||||
{
|
||||
public KRigElement[] GetHierarchy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c27f9465994402da2a00b6e82c4a580
|
||||
timeCreated: 1744271712
|
||||
8
Assets/KINEMATION/KAnimationCore/Runtime/Rig/IRigUser.cs
Normal file
8
Assets/KINEMATION/KAnimationCore/Runtime/Rig/IRigUser.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace KINEMATION.KAnimationCore.Runtime.Rig
|
||||
{
|
||||
public interface IRigUser
|
||||
{
|
||||
// Must return a reference to the used Rig Asset.
|
||||
public KRig GetRigAsset();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 906523edc5b146fb8837b1804a606af5
|
||||
timeCreated: 1705907873
|
||||
32
Assets/KINEMATION/KAnimationCore/Runtime/Rig/KPose.cs
Normal file
32
Assets/KINEMATION/KAnimationCore/Runtime/Rig/KPose.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using KINEMATION.KAnimationCore.Runtime.Core;
|
||||
|
||||
namespace KINEMATION.KAnimationCore.Runtime.Rig
|
||||
{
|
||||
// Represents the space we will modify bone transform in.
|
||||
public enum ESpaceType
|
||||
{
|
||||
BoneSpace,
|
||||
ParentBoneSpace,
|
||||
ComponentSpace,
|
||||
WorldSpace
|
||||
}
|
||||
|
||||
// Whether the operation is additive or absolute.
|
||||
public enum EModifyMode
|
||||
{
|
||||
Add,
|
||||
Replace,
|
||||
Ignore
|
||||
}
|
||||
|
||||
// Represents the pose for the specific rig element.
|
||||
[Serializable]
|
||||
public struct KPose
|
||||
{
|
||||
public KRigElement element;
|
||||
public KTransform pose;
|
||||
public ESpaceType space;
|
||||
public EModifyMode modifyMode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 054feb4bdc8a463ea7b6aba306d8cd64
|
||||
timeCreated: 1704783390
|
||||
138
Assets/KINEMATION/KAnimationCore/Runtime/Rig/KRig.cs
Normal file
138
Assets/KINEMATION/KAnimationCore/Runtime/Rig/KRig.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
// Designed by KINEMATION, 2024.
|
||||
|
||||
using KINEMATION.KAnimationCore.Runtime.Input;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using KINEMATION.KAnimationCore.Runtime.Attributes;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace KINEMATION.KAnimationCore.Runtime.Rig
|
||||
{
|
||||
public abstract class KRigBase : ScriptableObject, IRigProvider
|
||||
{
|
||||
public RuntimeAnimatorController targetAnimator;
|
||||
public List<KRigElement> rigHierarchy = new List<KRigElement>();
|
||||
|
||||
[CustomElementChainDrawer(false, true)]
|
||||
public List<KRigElementChain> rigElementChains = new List<KRigElementChain>();
|
||||
|
||||
public KRigElement[] GetHierarchy()
|
||||
{
|
||||
return rigHierarchy.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
// Character skeleton asset.
|
||||
public class KRig : KRigBase
|
||||
{
|
||||
public UserInputConfig inputConfig;
|
||||
public List<string> rigCurves = new List<string>();
|
||||
|
||||
public KRigElementChain GetElementChainByName(string chainName)
|
||||
{
|
||||
var chain = rigElementChains.Find(item => item.chainName.Equals(chainName));
|
||||
return chain;
|
||||
}
|
||||
|
||||
public KTransformChain GetPopulatedChain(string chainName, KRigComponent rigComponent)
|
||||
{
|
||||
KTransformChain result = new KTransformChain();
|
||||
var targetChain = GetElementChainByName(chainName);
|
||||
|
||||
if (targetChain == null)
|
||||
{
|
||||
Debug.LogError($"Rig `{name}`: `{chainName}` chain not found!");
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (var element in targetChain.elementChain)
|
||||
{
|
||||
result.transformChain.Add(rigComponent.GetRigTransform(element));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public List<int> rigDepths = new List<int>();
|
||||
private List<Object> _rigObservers = new List<Object>();
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
// Force update rig depths for compatibility reasons.
|
||||
int count = rigHierarchy.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var element = rigHierarchy[i];
|
||||
element.depth = rigDepths[i];
|
||||
rigHierarchy[i] = element;
|
||||
}
|
||||
}
|
||||
|
||||
public void ImportRig(KRigComponent rigComponent)
|
||||
{
|
||||
rigHierarchy.Clear();
|
||||
rigDepths.Clear();
|
||||
|
||||
rigComponent.RefreshHierarchy();
|
||||
|
||||
var hierarchy = rigComponent.GetRigTransforms();
|
||||
var depths = rigComponent.GetHierarchyDepths();
|
||||
|
||||
for (int i = 0; i < hierarchy.Length; i++)
|
||||
{
|
||||
rigHierarchy.Add(new KRigElement(i, hierarchy[i].transform.name));
|
||||
rigDepths.Add(depths[i]);
|
||||
}
|
||||
|
||||
NotifyObservers();
|
||||
|
||||
EditorUtility.SetDirty(this);
|
||||
AssetDatabase.SaveAssetIfDirty(this);
|
||||
}
|
||||
|
||||
public KRigElement GetElementByName(string targetName)
|
||||
{
|
||||
return rigHierarchy.Find(item => item.name.Equals(targetName));
|
||||
}
|
||||
|
||||
public void RegisterRigObserver(Object newRigObserver)
|
||||
{
|
||||
// Only register Rig Observers.
|
||||
IRigObserver observer = (IRigObserver) newRigObserver;
|
||||
if (observer == null) return;
|
||||
|
||||
if (_rigObservers.Contains(newRigObserver))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_rigObservers.Add(newRigObserver);
|
||||
EditorUtility.SetDirty(this);
|
||||
}
|
||||
|
||||
public void UnRegisterObserver(Object rigObserver)
|
||||
{
|
||||
_rigObservers.Remove(rigObserver);
|
||||
EditorUtility.SetDirty(this);
|
||||
}
|
||||
|
||||
public void NotifyObservers()
|
||||
{
|
||||
List<Object> validObservers = new List<Object>();
|
||||
foreach (var observer in _rigObservers)
|
||||
{
|
||||
if (observer is IRigObserver obj)
|
||||
{
|
||||
obj.OnRigUpdated();
|
||||
validObservers.Add(observer);
|
||||
}
|
||||
}
|
||||
|
||||
_rigObservers = validObservers;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
11
Assets/KINEMATION/KAnimationCore/Runtime/Rig/KRig.cs.meta
Normal file
11
Assets/KINEMATION/KAnimationCore/Runtime/Rig/KRig.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c9c04639ae548bdb0a8e927492d029d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
176
Assets/KINEMATION/KAnimationCore/Runtime/Rig/KRigComponent.cs
Normal file
176
Assets/KINEMATION/KAnimationCore/Runtime/Rig/KRigComponent.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
// Designed by KINEMATION, 2024.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using KINEMATION.KAnimationCore.Runtime.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KINEMATION.KAnimationCore.Runtime.Rig
|
||||
{
|
||||
public class KRigComponent : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private List<Transform> hierarchy = new List<Transform>();
|
||||
private List<KVirtualElement> _virtualElements;
|
||||
private Dictionary<string, int> _hierarchyMap;
|
||||
private List<KTransform> _cachedHierarchyPose;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[SerializeField] private List<int> hierarchyDepths = new List<int>();
|
||||
|
||||
public bool CompareRig(KRig compareTo)
|
||||
{
|
||||
if (compareTo == null || hierarchy == null || compareTo.rigHierarchy.Count != hierarchy.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int count = hierarchy.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (!compareTo.rigHierarchy[i].name.Equals(hierarchy[i].name)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int[] GetHierarchyDepths()
|
||||
{
|
||||
return hierarchyDepths.ToArray();
|
||||
}
|
||||
|
||||
public void RefreshHierarchy()
|
||||
{
|
||||
hierarchy.Clear();
|
||||
hierarchyDepths.Clear();
|
||||
TraverseHierarchyByLayer(transform, 0);
|
||||
}
|
||||
|
||||
public Transform[] GetHierarchy()
|
||||
{
|
||||
if (hierarchy == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return hierarchy.ToArray();
|
||||
}
|
||||
|
||||
public bool Contains(string entry)
|
||||
{
|
||||
if (hierarchy == null) return false;
|
||||
|
||||
HashSet<string> set = new HashSet<string>();
|
||||
foreach (var element in hierarchy)
|
||||
{
|
||||
set.Add(element.name);
|
||||
}
|
||||
|
||||
return set.Contains(entry);
|
||||
}
|
||||
|
||||
private void TraverseHierarchyByLayer(Transform currentTransform, int depth)
|
||||
{
|
||||
hierarchy.Add(currentTransform);
|
||||
hierarchyDepths.Add(depth);
|
||||
|
||||
foreach (Transform child in currentTransform)
|
||||
{
|
||||
TraverseHierarchyByLayer(child, depth + 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
// Register Virtual Elements.
|
||||
_virtualElements = new List<KVirtualElement>();
|
||||
KVirtualElement[] virtualElements = GetComponentsInChildren<KVirtualElement>();
|
||||
|
||||
foreach (var virtualElement in virtualElements)
|
||||
{
|
||||
_virtualElements.Add(virtualElement);
|
||||
}
|
||||
|
||||
// Map the hierarchy indexes to the element names.
|
||||
_hierarchyMap = new Dictionary<string, int>();
|
||||
|
||||
int count = hierarchy.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
_hierarchyMap.TryAdd(hierarchy[i].name, i);
|
||||
}
|
||||
|
||||
_cachedHierarchyPose = new List<KTransform>();
|
||||
}
|
||||
|
||||
public void AnimateVirtualElements()
|
||||
{
|
||||
foreach (var virtualElement in _virtualElements)
|
||||
{
|
||||
virtualElement.Animate();
|
||||
}
|
||||
}
|
||||
|
||||
public Transform[] GetRigTransforms()
|
||||
{
|
||||
return hierarchy.ToArray();
|
||||
}
|
||||
|
||||
public Transform GetRigTransform(KRigElement rigElement)
|
||||
{
|
||||
int index = rigElement.index;
|
||||
|
||||
// Invalid index, try to use the element name instead.
|
||||
if (index < 0 || index > hierarchy.Count - 1)
|
||||
{
|
||||
index = _hierarchyMap[rigElement.name];
|
||||
}
|
||||
|
||||
// Total failure, return null.
|
||||
if (index < 0 || index > hierarchy.Count - 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return hierarchy[index].transform;
|
||||
}
|
||||
|
||||
public Transform GetRigTransform(string elementName)
|
||||
{
|
||||
if (_hierarchyMap.TryGetValue(elementName, out var element))
|
||||
{
|
||||
return hierarchy[element];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Transform GetRigTransform(int elementIndex)
|
||||
{
|
||||
if (elementIndex < 0 || elementIndex > hierarchy.Count - 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return hierarchy[elementIndex].transform;
|
||||
}
|
||||
|
||||
public void CacheHierarchyPose()
|
||||
{
|
||||
_cachedHierarchyPose.Clear();
|
||||
foreach (var element in hierarchy) _cachedHierarchyPose.Add(new KTransform(element,
|
||||
false));
|
||||
}
|
||||
|
||||
public void ApplyHierarchyCachedPose()
|
||||
{
|
||||
int count = hierarchy.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var cachedPose = _cachedHierarchyPose[i];
|
||||
|
||||
hierarchy[i].localPosition = cachedPose.position;
|
||||
hierarchy[i].localRotation = cachedPose.rotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e03e7ed42ce9470c899fc6cc550571e6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
22
Assets/KINEMATION/KAnimationCore/Runtime/Rig/KRigElement.cs
Normal file
22
Assets/KINEMATION/KAnimationCore/Runtime/Rig/KRigElement.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
// Designed by KINEMATION, 2024.
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KINEMATION.KAnimationCore.Runtime.Rig
|
||||
{
|
||||
[Serializable]
|
||||
public struct KRigElement
|
||||
{
|
||||
public string name;
|
||||
[HideInInspector] public int index;
|
||||
public int depth;
|
||||
|
||||
public KRigElement(int index = -1, string name = "None", int depth = -1)
|
||||
{
|
||||
this.index = index;
|
||||
this.name = name;
|
||||
this.depth = depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba9819a027d34b42a29b91a6cdaa5bbf
|
||||
timeCreated: 1704271222
|
||||
123
Assets/KINEMATION/KAnimationCore/Runtime/Rig/KRigElementChain.cs
Normal file
123
Assets/KINEMATION/KAnimationCore/Runtime/Rig/KRigElementChain.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
// Designed by KINEMATION, 2024.
|
||||
|
||||
using KINEMATION.KAnimationCore.Runtime.Core;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KINEMATION.KAnimationCore.Runtime.Rig
|
||||
{
|
||||
[Serializable]
|
||||
public class KRigElementChain
|
||||
{
|
||||
public int Count => elementChain.Count;
|
||||
|
||||
public string chainName;
|
||||
[HideInInspector] public List<KRigElement> elementChain = new List<KRigElement>();
|
||||
|
||||
public KRigElementChain GetCopy()
|
||||
{
|
||||
KRigElementChain copy = new KRigElementChain();
|
||||
copy.chainName = chainName;
|
||||
foreach (var element in elementChain) copy.elementChain.Add(element);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
// A simplified version of the KRigElementChain, which contains transforms only.
|
||||
public class KTransformChain
|
||||
{
|
||||
public List<Transform> transformChain = new List<Transform>();
|
||||
public List<KTransform> cachedTransforms = new List<KTransform>();
|
||||
public ESpaceType spaceType;
|
||||
|
||||
public void CacheTransforms(ESpaceType targetSpace, Transform root = null)
|
||||
{
|
||||
cachedTransforms.Clear();
|
||||
spaceType = targetSpace;
|
||||
|
||||
foreach (var element in transformChain)
|
||||
{
|
||||
KTransform cache = new KTransform();
|
||||
|
||||
if (targetSpace == ESpaceType.WorldSpace)
|
||||
{
|
||||
cache.position = element.position;
|
||||
cache.rotation = element.rotation;
|
||||
}
|
||||
else if (targetSpace == ESpaceType.ComponentSpace)
|
||||
{
|
||||
if (root == null)
|
||||
{
|
||||
root = element.root;
|
||||
}
|
||||
|
||||
cache.position = root.InverseTransformPoint(element.position);
|
||||
cache.rotation = Quaternion.Inverse(root.rotation) * element.rotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
cache.position = element.localPosition;
|
||||
cache.rotation = element.localRotation;
|
||||
}
|
||||
|
||||
cachedTransforms.Add(cache);
|
||||
}
|
||||
}
|
||||
|
||||
public void BlendTransforms(float weight)
|
||||
{
|
||||
int count = transformChain.Count;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Transform element = transformChain[i];
|
||||
KTransform cache = cachedTransforms[i];
|
||||
|
||||
KPose pose = new KPose()
|
||||
{
|
||||
modifyMode = EModifyMode.Replace,
|
||||
pose = cache,
|
||||
space = spaceType
|
||||
};
|
||||
|
||||
KAnimationMath.ModifyTransform(element.root, element, pose, weight);
|
||||
}
|
||||
}
|
||||
|
||||
public float GetLength(Transform root = null)
|
||||
{
|
||||
float chainLength = 0f;
|
||||
int count = transformChain.Count;
|
||||
|
||||
if (count > 0 && root == null) root = transformChain[0];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Transform targetBone = transformChain[i];
|
||||
|
||||
if (count == 1)
|
||||
{
|
||||
Vector3 targetMS = root.InverseTransformPoint(targetBone.position);
|
||||
chainLength = targetMS.magnitude;
|
||||
}
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
chainLength += (targetBone.position - transformChain[i - 1].position).magnitude;
|
||||
}
|
||||
}
|
||||
|
||||
return chainLength;
|
||||
}
|
||||
|
||||
public bool IsValid()
|
||||
{
|
||||
if (transformChain == null || cachedTransforms == null) return false;
|
||||
if (transformChain.Count == 0) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33155135ddde45ec8689a8c186f23deb
|
||||
timeCreated: 1704271199
|
||||
@@ -0,0 +1,15 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace KINEMATION.KAnimationCore.Runtime.Rig
|
||||
{
|
||||
public class KVirtualElement : MonoBehaviour
|
||||
{
|
||||
public Transform targetBone;
|
||||
|
||||
public void Animate()
|
||||
{
|
||||
transform.position = targetBone.position;
|
||||
transform.rotation = targetBone.rotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f3351c9a16a41d9b4e52958975b758b
|
||||
timeCreated: 1707634755
|
||||
Reference in New Issue
Block a user