1.水平移动应用动画跟运动,上台阶使用Rigibody
public class RigibodyMoveTest :MonoBehaviour
{
private Rigidbody m_Rigidbody;
private float m_InputH;
private float m_InputV;
private Animator m_Animator;
private PhysicMaterial m_FrictionPhysics, m_MaxFrictionPhysics, m_SlippyPhysics; // create PhysicMaterial for the Rigidbody
private CapsuleCollider m_CapsuleCollider;
private float m_ColliderRadius, m_ColliderHeight; // storage capsule collider extra information
private Vector3 m_ColliderCenter; // storage the center of the capsule collider info
private Vector2 m_Input;
private Vector3 m_MoveDir;
private float m_Velocity;// velocity to apply to rigdibody
public float stepOffsetEnd = 0.45;
public float stepOffsetStart = 0f;
public float stepSmooth = 4f;
public LayerMask groundLayer = 1 << 0;
public float moveSpeed = 1f;
public bool useCustomRootMotion;
public bool isStep;
private void Init()
{
m_Animator = GetComponent<Animator>();
m_Animator.updateMode = AnimatorUpdateMode.AnimatePhysics;
// rigidbody info
m_Rigidbody = GetComponent<Rigidbody>();
// capsule collider info
m_CapsuleCollider = GetComponent<CapsuleCollider>();
// save your collider preferences
m_ColliderCenter = GetComponent<CapsuleCollider>().center;
m_ColliderRadius = GetComponent<CapsuleCollider>().radius;
m_ColliderHeight = GetComponent<CapsuleCollider>().height;
CreatPhysicMaterial();
// avoid collision detection with inside colliders
Collider[] AllColliders = this.GetComponentsInChildren<Collider>();
for (int i = 0; i < AllColliders.Length; i++)
{
Physics.IgnoreCollision(m_CapsuleCollider, AllColliders[i]);
}
}
void Start()
{
Init();
}
void Update()
{
m_InputH = Input.GetAxis("Horizontal");
m_InputV = Input.GetAxis("Vertical");
m_Input = new Vector2(m_InputH, m_InputV);
if (m_Input.sqrMagnitude > 0.1f)
{
m_Animator.SetFloat("Forward", 1f);
}
else
{
m_Animator.SetFloat("Forward", 0f);
}
Vector3 vel = m_Rigidbody.velocity;
m_MoveDir = new Vector3(m_InputH, 0f,m_InputV);
if (Mathf.Abs(m_Input.x) > 0.05f || Mathf.Abs(m_Input.y) > 0.05f)
{
//给刚体更新新的向量速度
//m_Rigidbody.velocity = new Vector3(m_Input.x * moveSpeed, vel.y, m_Input.y * moveSpeed);
transform.rotation = Quaternion.LookRotation(new Vector3(m_Input.x, 0, m_Input.y));
}
isStep= StepOffset();
}
private void OnAnimatorMove()
{
if (Time.deltaTime == 0) return;
if (useCustomRootMotion)
{
if (m_Input.magnitude > 0.1f)
{
this.m_Velocity = moveSpeed;
var deltaPosition = new Vector3(m_Animator.deltaPosition.x, transform.position.y, m_Animator.deltaPosition.z);
Vector3 v = (deltaPosition * (m_Velocity > 0 ? m_Velocity : 1f)) / Time.deltaTime;
v.y = m_Rigidbody.velocity.y;
m_Rigidbody.velocity = Vector3.Lerp(m_Rigidbody.velocity, v, 20f * Time.deltaTime);
}
else
{
transform.rotation = m_Animator.rootRotation;
transform.position = m_Animator.rootPosition;
m_Rigidbody.velocity = new Vector3(0f, m_Rigidbody.velocity.y, 0f);
}
}
else
{
m_Animator.ApplyBuiltinRootMotion();
}
}
private bool StepOffset()
{
if (m_Input.sqrMagnitude < 0.1 /*|| !isGround*/) return false;
var _hit = new RaycastHit();
var _movementDirection = /*isStrafing && m_Input.magnitude > 0 ? (transform.right * m_Input.x + transform.forward * m_Input.y).normalized :*/ transform.forward;
Ray rayStep = new Ray((transform.position + new Vector3(0, stepOffsetEnd, 0) + _movementDirection * ((m_CapsuleCollider).radius + 0.05f)), Vector3.down);
if (Physics.Raycast(rayStep, out _hit, stepOffsetEnd - stepOffsetStart, groundLayer) && !_hit.collider.isTrigger)
{
if (_hit.point.y >= (transform.position.y) && _hit.point.y <= (transform.position.y + stepOffsetEnd))
{
var _speed = Mathf.Clamp(m_Input.magnitude, 0, 1f);
var velocityDirection = (_hit.point - transform.position).normalized;
var vel = m_Rigidbody.velocity;
vel.y = (velocityDirection * stepSmooth * (_speed * (m_Velocity > 1 ? m_Velocity : 1))).y;
m_Rigidbody.velocity = vel;
return true;
}
}
if (Physics.SphereCast(rayStep, m_CapsuleCollider.radius * 0.9f, out _hit, stepOffsetEnd - stepOffsetStart, groundLayer) && !_hit.collider.isTrigger)
{
if (_hit.point.y >= (transform.position.y) && _hit.point.y <= (transform.position.y + stepOffsetEnd))
{
var _speed = Mathf.Clamp(m_Input.magnitude, 0, 1f);
var velocityDirection = (_hit.point - transform.position).normalized;
var vel = m_Rigidbody.velocity;
vel.y = (velocityDirection * stepSmooth * (_speed * (m_Velocity > 1 ? m_Velocity : 1))).y;
m_Rigidbody.velocity = vel;
return true;
}
}
return false;
}
}