前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Unity动画☀️9. 木头自转、扛起木头、OnTriggerEnter

Unity动画☀️9. 木头自转、扛起木头、OnTriggerEnter

作者头像
星河造梦坊官方
发布2024-08-14 16:13:06
发布2024-08-14 16:13:06
12100
代码可运行
举报
运行总次数:0
代码可运行

🟥 给场景添加木头

1️⃣ 导入木头Log,找回丢失的贴图,通过Perfab的Model—Scale Factor调节导入比例—0.3

2️⃣ 控制策略:通过检测木头与人物的碰撞,控制人物捡起木头

3️⃣ 给木头添加Sphere Collider,Radius调整合适大小,勾选Is Trigger

🟧 木头自转

给木头添加代码,控制木头旋转

代码语言:javascript
代码运行次数:0
运行
复制
using UnityEngine;

public class RotateSelf : MonoBehaviour {
    
    public float rotateSpeed=90;
    
	void Update () {
        transform.Rotate(Vector3.up * rotateSpeed*Time.deltaTime, Space.World);  //速度*时间=每一帧旋转多少度
	}
}

🟨 扛起木头

控制策略:通过人物的Character Controller检测与木头是否碰撞,若碰撞则销毁木头,在肩部激活预定义的木头

肩部的木头预先需放置于角色结构树的Neck下,与脖子或头平级,这样木头便会随着头部运动而同步运动

代码语言:javascript
代码运行次数:0
运行
复制
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

动画展示:

大家还有什么问题,欢迎在下方留言!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-09-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 🟥 给场景添加木头
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档