1️⃣ 导入木头Log,找回丢失的贴图,通过Perfab的Model—Scale Factor调节导入比例—0.3
2️⃣ 控制策略:通过检测木头与人物的碰撞,控制人物捡起木头
3️⃣ 给木头添加Sphere Collider,Radius调整合适大小,勾选Is Trigger
🟧 木头自转
给木头添加代码,控制木头旋转
using UnityEngine;
public class RotateSelf : MonoBehaviour {
public float rotateSpeed=90;
void Update () {
transform.Rotate(Vector3.up * rotateSpeed*Time.deltaTime, Space.World); //速度*时间=每一帧旋转多少度
}
}
🟨 扛起木头
控制策略:通过人物的Character Controller检测与木头是否碰撞,若碰撞则销毁木头,在肩部激活预定义的木头
肩部的木头预先需放置于角色结构树的Neck下,与脖子或头平级,这样木头便会随着头部运动而同步运动
using UnityEngine;
public class Player : MonoBehaviour {
private Animator anim;
private int speedRotateID = Animator.StringToHash("SpeedRotate");
private int speedZID = Animator.StringToHash("SpeedZ");
int vaultID = Animator.StringToHash("Vault");
private Vector3 matchTarget;
private CharacterController characterController;
private int vaultCurveID = Animator.StringToHash("vaultCurve");
private int sliderID = Animator.StringToHash("Slider");
private int sliderCurveID = Animator.StringToHash("sliderCurve");
public GameObject unityLog;
void Start () {
anim = GetComponent<Animator>();
characterController = GetComponent<CharacterController>();
}
void Update () {
anim.SetFloat(speedZID, Input.GetAxis("Vertical") * 4.5f);
anim.SetFloat(speedRotateID, Input.GetAxis("Horizontal")*126);
ProcessVault();
ProcessSlider();
}
private void ProcessVault()
{
if (anim.GetFloat(speedZID) > 3 && anim.GetCurrentAnimatorStateInfo(0).IsName("LocalMotion"))
{
RaycastHit hit;
if (Physics.Raycast(transform.position + Vector3.up * 0.3f, transform.forward, out hit, 4.5f))
{
if (hit.collider.tag == "Obstacle")
{
if (hit.distance > 3)
{
Vector3 point = hit.point;
point.y = hit.transform.position.y + hit.collider.bounds.size.y + 0.09f; //普通的cube在水平面时默认中心高度y=0.5,但此模型水平中心高度为0(和底边一致)!,所以是它最低点位置+Y轴的大小
matchTarget = point;
anim.SetBool(vaultID, true);
}
}
}
else anim.SetBool(vaultID, false);
}
characterController.enabled = anim.GetFloat(vaultCurveID) < 0.5f;
if (anim.GetCurrentAnimatorStateInfo(0).IsName("Vault"))
{
anim.MatchTarget(matchTarget, Quaternion.identity, AvatarTarget.LeftHand, new MatchTargetWeightMask(Vector3.one, 0), 0.32f, 0.4f);
}
}
private void ProcessSlider()
{
if (anim.GetFloat(speedZID) > 3 && anim.GetCurrentAnimatorStateInfo(0).IsName("LocalMotion"))
{
RaycastHit hit;
if (Physics.Raycast(transform.position + Vector3.up * 1.5f, transform.forward, out hit, 5f))
{
if (hit.collider.tag == "Obstacle")
{
if (hit.distance <2.8)
{
Vector3 point = hit.point;
point.y = 0 ;
matchTarget = point+transform.forward*2;
anim.SetBool(sliderID, true);
}
}
}
}
else anim.SetBool(sliderID, false);
if (anim.GetCurrentAnimatorStateInfo(0).IsName("Slider"))
{
anim.MatchTarget(matchTarget, Quaternion.identity, AvatarTarget.Root, new MatchTargetWeightMask(new Vector3(1,0,1), 0), 0.38f, 0.67f);
}
if (anim.GetCurrentAnimatorStateInfo(0).IsName("Slider" ))
{
characterController.enabled = anim.GetFloat(sliderCurveID) < 0.5f;
}
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Log")
{
Destroy(other.gameObject);
unityLog.SetActive(true);
}
}
}
OnTriggerEnter
该函数触发的条件:
1️⃣ 两个物体都必须有碰撞器(Collider)组件;
2️⃣ 其中一个物体的碰撞器(Collider)的IsTrigger属性必须勾上;
3、最重要的一点,其中一个物体必须有刚体(Rigidbody)组件。如果是一个运动的物体去碰撞一个静止的物体,则刚体(Rigidbody)组件必须加在运动的物体上,否则无法触发OnOnTriggerEnter函数。
此动画人物为Character Controller组件,木头为Sphere Collider组件,且勾选了Is Trigger
动画展示:
大家还有什么问题,欢迎在下方留言!