You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
8.1 KiB
C#
223 lines
8.1 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
using System;
|
|
|
|
namespace RootMotion.Dynamics
|
|
{
|
|
public partial class PuppetMaster : MonoBehaviour
|
|
{
|
|
#if UNITY_EDITOR
|
|
|
|
[ContextMenu("Save Settings As Humanoid Config")]
|
|
private void SaveToHumanoidConfig()
|
|
{
|
|
var path = "Assets/Saved Humanoid Config.asset";
|
|
|
|
if (targetRoot == null)
|
|
{
|
|
Debug.LogWarning("Please assign 'Target Root' for PuppetMaster using a Humanoid Config.", transform);
|
|
return;
|
|
}
|
|
|
|
if (targetAnimator == null)
|
|
{
|
|
Debug.LogError("PuppetMaster 'Target Root' does not have an Animator component. Can not use Humanoid Config.", transform);
|
|
return;
|
|
}
|
|
|
|
if (!targetAnimator.isHuman)
|
|
{
|
|
Debug.LogError("PuppetMaster target is not a Humanoid. Can not use Humanoid Config.", transform);
|
|
return;
|
|
}
|
|
|
|
var p = ScriptableObject.CreateInstance<PuppetMasterHumanoidConfig>();
|
|
|
|
p.state = state;
|
|
p.stateSettings = stateSettings;
|
|
p.mode = mode;
|
|
p.blendTime = blendTime;
|
|
p.fixTargetTransforms = fixTargetTransforms;
|
|
p.solverIterationCount = solverIterationCount;
|
|
p.visualizeTargetPose = visualizeTargetPose;
|
|
p.mappingWeight = mappingWeight;
|
|
p.pinWeight = pinWeight;
|
|
p.muscleWeight = muscleWeight;
|
|
p.muscleSpring = muscleSpring;
|
|
p.muscleDamper = muscleDamper;
|
|
p.pinPow = pinPow;
|
|
p.pinDistanceFalloff = pinDistanceFalloff;
|
|
p.angularPinning = angularPinning;
|
|
p.updateJointAnchors = updateJointAnchors;
|
|
p.supportTranslationAnimation = supportTranslationAnimation;
|
|
p.angularLimits = angularLimits;
|
|
p.internalCollisions = internalCollisions;
|
|
|
|
p.muscles = new PuppetMasterHumanoidConfig.HumanoidMuscle[muscles.Length];
|
|
var allHumanBodyBones = (HumanBodyBones[])System.Enum.GetValues(typeof(HumanBodyBones));
|
|
|
|
for (int i = 0; i < muscles.Length; i++)
|
|
{
|
|
var m = muscles[i];
|
|
var h = new PuppetMasterHumanoidConfig.HumanoidMuscle();
|
|
h.props = new Muscle.Props();
|
|
|
|
h.bone = GetHumanBodyBone(m.target, allHumanBodyBones);
|
|
h.props.group = m.props.group;
|
|
h.props.mappingWeight = m.props.mappingWeight;
|
|
h.props.muscleDamper = m.props.muscleDamper;
|
|
h.props.muscleWeight = m.props.muscleWeight;
|
|
h.props.pinWeight = m.props.pinWeight;
|
|
|
|
p.muscles[i] = h;
|
|
}
|
|
|
|
UnityEditor.AssetDatabase.CreateAsset(p, path);
|
|
UnityEditor.AssetDatabase.SaveAssets();
|
|
UnityEditor.AssetDatabase.Refresh();
|
|
var saved = UnityEditor.AssetDatabase.LoadAssetAtPath(path, typeof(PuppetMasterHumanoidConfig)) as PuppetMasterHumanoidConfig;
|
|
if (saved != null)
|
|
{
|
|
Debug.Log("PuppetMasterHumanoidConfig successfully created at " + path);
|
|
UnityEditor.Selection.activeObject = saved;
|
|
}
|
|
}
|
|
|
|
private HumanBodyBones GetHumanBodyBone(Transform t, HumanBodyBones[] allBones)
|
|
{
|
|
for (int i = 0; i < allBones.Length - 1; i++)
|
|
{
|
|
var bone = allBones[i];
|
|
if (targetAnimator.GetBoneTransform(bone) == t) return bone;
|
|
}
|
|
//Debug.LogError("Unable to find HumanBodyBone of Transform " + t.name, transform);
|
|
return HumanBodyBones.LastBone;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
[CreateAssetMenu(fileName = "PuppetMaster Humanoid Config", menuName = "PuppetMaster/Humanoid Config", order = 1)]
|
|
public class PuppetMasterHumanoidConfig : ScriptableObject
|
|
{
|
|
|
|
[System.Serializable]
|
|
public class HumanoidMuscle
|
|
{
|
|
[HideInInspector] public string name;
|
|
public HumanBodyBones bone;
|
|
public Muscle.Props props;
|
|
}
|
|
|
|
[LargeHeader("Simulation")]
|
|
|
|
public PuppetMaster.State state;
|
|
public PuppetMaster.StateSettings stateSettings = PuppetMaster.StateSettings.Default;
|
|
public PuppetMaster.Mode mode;
|
|
public float blendTime = 0.1f;
|
|
public bool fixTargetTransforms = true;
|
|
public int solverIterationCount = 6;
|
|
public bool visualizeTargetPose = true;
|
|
|
|
[LargeHeader("Master Weights")]
|
|
|
|
[Range(0f, 1f)] public float mappingWeight = 1f;
|
|
[Range(0f, 1f)] public float pinWeight = 1f;
|
|
[Range(0f, 1f)] public float muscleWeight = 1f;
|
|
|
|
[LargeHeader("Joint and Muscle Settings")]
|
|
|
|
public float muscleSpring = 100f;
|
|
public float muscleDamper = 0f;
|
|
[Range(1f, 8f)] public float pinPow = 4f;
|
|
[Range(0f, 100f)] public float pinDistanceFalloff = 5;
|
|
public bool angularPinning;
|
|
public bool updateJointAnchors = true;
|
|
public bool supportTranslationAnimation;
|
|
public bool angularLimits;
|
|
public bool internalCollisions;
|
|
|
|
[LargeHeader("Individual Muscle Settings")]
|
|
|
|
public HumanoidMuscle[] muscles = new HumanoidMuscle[0];
|
|
|
|
/// <summary>
|
|
/// Applies this config to the specified PuppetMaster.
|
|
/// </summary>
|
|
/// <param name="p">P.</param>
|
|
public void ApplyTo(PuppetMaster p)
|
|
{
|
|
if (p.targetRoot == null)
|
|
{
|
|
Debug.LogWarning("Please assign 'Target Root' for PuppetMaster using a Humanoid Config.", p.transform);
|
|
return;
|
|
}
|
|
|
|
if (p.targetAnimator == null)
|
|
{
|
|
Debug.LogError("PuppetMaster 'Target Root' does not have an Animator component. Can not use Humanoid Config.", p.transform);
|
|
return;
|
|
}
|
|
|
|
if (!p.targetAnimator.isHuman)
|
|
{
|
|
Debug.LogError("PuppetMaster target is not a Humanoid. Can not use Humanoid Config.", p.transform);
|
|
return;
|
|
}
|
|
|
|
p.state = state;
|
|
p.stateSettings = stateSettings;
|
|
p.mode = mode;
|
|
p.blendTime = blendTime;
|
|
p.fixTargetTransforms = fixTargetTransforms;
|
|
p.solverIterationCount = solverIterationCount;
|
|
p.visualizeTargetPose = visualizeTargetPose;
|
|
p.mappingWeight = mappingWeight;
|
|
p.pinWeight = pinWeight;
|
|
p.muscleWeight = muscleWeight;
|
|
p.muscleSpring = muscleSpring;
|
|
p.muscleDamper = muscleDamper;
|
|
p.pinPow = pinPow;
|
|
p.pinDistanceFalloff = pinDistanceFalloff;
|
|
p.angularPinning = angularPinning;
|
|
p.updateJointAnchors = updateJointAnchors;
|
|
p.supportTranslationAnimation = supportTranslationAnimation;
|
|
p.angularLimits = angularLimits;
|
|
p.internalCollisions = internalCollisions;
|
|
|
|
for (int i = 0; i < muscles.Length; i++)
|
|
{
|
|
var m = GetMuscle(muscles[i].bone, p.targetAnimator, p);
|
|
if (m == null && i < p.muscles.Length)
|
|
{
|
|
m = p.muscles[i];
|
|
}
|
|
|
|
if (m != null)
|
|
{
|
|
var h = muscles[i];
|
|
m.props.group = h.props.group;
|
|
m.props.mappingWeight = h.props.mappingWeight;
|
|
//m.props.mapPosition = h.props.mapPosition;
|
|
m.props.muscleDamper = h.props.muscleDamper;
|
|
m.props.muscleWeight = h.props.muscleWeight;
|
|
m.props.pinWeight = h.props.pinWeight;
|
|
}
|
|
}
|
|
}
|
|
|
|
private Muscle GetMuscle(HumanBodyBones boneId, Animator animator, PuppetMaster puppetMaster)
|
|
{
|
|
if (boneId == HumanBodyBones.LastBone) return null;
|
|
|
|
Transform bone = animator.GetBoneTransform(boneId);
|
|
if (bone == null) return null;
|
|
|
|
foreach (Muscle m in puppetMaster.muscles)
|
|
{
|
|
if (m.target == bone) return m;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
} |