Unity 实现 3A 游戏风格的物品拾取到手上交互功能

目录

Unity 实现 3A 游戏风格的物品拾取到手上交互功能

一、前期准备

二、Timeline 动画设置

三、代码实现

(一)修改角色控制器脚本

(二)创建player_pick_up_ability脚本

(三)创建pick_up_object_on_table脚本

四、在 Unity 中配置脚本


在 3A 游戏中,物品拾取到手上的交互功能是增强游戏真实感与沉浸感的关键环节。本期教程,我们将详细讲解如何运用 Unity 引擎,结合 Timeline 和代码,实现这一功能。即便你没有观看过上期视频,也能轻松跟上节奏,独立学习。

一、前期准备

  1. 场景搭建:准备一个全新的 Pro Ground 场景。制作一张桌子,在 Hierarchy 面板中新建一个空节点作为桌子的父物体,方便整体控制。从其他地方拷贝一个盒子,调整其位置,并将其 Tag 修改为 “box”。若没有 “box” 标签,点击 “ADD tag” 添加后再修改。
  2. 碰撞体设置:为盒子添加 Box Collider 组件,勾选 “is trigger” 选项,点击 “编辑” 动态调整可触发的位置区域,确保玩家进入该区域时才能拾取物体。
  3. 人物手部节点添加:将人物放置到桌子附近,在人物层级中找到手部部分,右键添加一个球体。这个球体代表手上物体所在的点,调整其大小和位置,后续拾取的物体将作为它的子物体。在实际项目中,可能会有多个这样的点,用于适配不同的拾取物体。

二、Timeline 动画设置

  1. 打开 Timeline 窗口:若在界面中未找到 Timeline 窗口,可在 “Windows” 菜单下的 “Second thing” 中点击 “Timeline” 打开。
  2. 创建 Timeline 并添加轨道:选择桌子物体,在 Timeline 窗口中点击 “Create”,并保存 Playable 资产。接着添加一个 Animation 轨道,暂时将主角人物添加进来。
  3. 添加动画:把之前下载好的拾取装备动作添加到工程中。选择该动作文件,在 “RG” 标签下切换成 “human”,在 “Animation” 标签下更改动画名称。切换回 Timeline 窗口,找到拾取动画文件,拖动到轨道上,再找到站立动作添加到后面,让动画有一个合适的过渡。
  4. 调整动画设置:拖动滑杆查看效果时,会发现角色目前会回归到零点的站立位置。点击轨道,选择 “按照场景的偏移变换”,并将轨道改名为 “玩家的轨道”。调整桌子位置时,若出现回跳现象,可点击 Timeline 窗口的锁头标志锁定窗口,避免失去焦点。

三、代码实现

(一)修改角色控制器脚本

  1. 添加布尔变量:选择主角的角色,找到 “第三人称控制器” 脚本,双击打开代码。添加一个布尔型的类成员变量,用于标记是否开关移动操作。

private bool isMovingDisabled = false;

  1. 在 Update 中增加判断:在Update方法中增加一段判断代码,用于控制角色移动。

void Update()
{
    if (isMovingDisabled)
    {
        // 这里可以根据需求添加暂停角色移动相关的逻辑,例如设置角色速度为0
        return;
    }
    // 原有的角色移动控制代码
}

(二)创建player_pick_up_ability脚本

  1. 定义接口:这个脚本用于赋予玩家拾取物体的能力。首先定义一个接口i_can_pick_up

public interface i_can_pick_up
{
    void pick_up();
    bool pick_up_complete { get; set; }
}

  1. 碰撞触发函数:编写碰撞触发函数,当玩家碰撞到标签为 “box” 的物体时,判断其是否具有可拾取的接口组件,若有则加入到可拾取列表中。

private List<i_can_pick_up> pickableObjects = new List<i_can_pick_up>();
private void OnTriggerEnter(Collider other)
{
    if (other.CompareTag("box"))
    {
        i_can_pick_up pickable = other.GetComponent<i_can_pick_up>();
        if (pickable!= null)
        {
            pickableObjects.Add(pickable);
        }
    }
}
private void OnTriggerExit(Collider other)
{
    if (other.CompareTag("box"))
    {
        i_can_pick_up pickable = other.GetComponent<i_can_pick_up>();
        if (pickable!= null)
        {
            pickableObjects.Remove(pickable);
        }
    }
}

  1. 添加拾取操作代码:增加公共属性获取手部的transform,并保存当前拥有拾取接口的目标。当操作函数被执行时,判断是否有当前正在拾取的目标,若有则从列表中取得第一个进行拾取动作。

public Transform hand;
private i_can_pick_up currentPickable;
public void PickUp()
{
    if (pickableObjects.Count > 0)
    {
        currentPickable = pickableObjects[0];
        currentPickable.pick_up();
    }
}
private void Update()
{
    if (currentPickable!= null && currentPickable.pick_up_complete)
    {
        currentPickable = null;
    }
}

(三)创建pick_up_object_on_table脚本

  1. 实现接口:在类上面添加可拾取的接口i_can_pick_up,并实现接口中的代码。

public class pick_up_object_on_table : MonoBehaviour, i_can_pick_up
{
    public float pickUpTime;
    public GameObject pickedObject;
    public Transform playerStandPoint;
    private bool isPickUpComplete = false;
    public bool pick_up_complete
    {
        get { return isPickUpComplete; }
        set { isPickUpComplete = value; }
    }
    public void pick_up()
    {
        // 开启协程控制动画播放
        StartCoroutine(PickUpCoroutine());
    }
}

  1. 协程控制动画播放:用一个协程来实现对动画播放的控制,在动画播放前后控制角色的移动状态,并标记拾取完成状态。

private IEnumerator PickUpCoroutine()
{
    // 获取角色控制器脚本
    var characterController = GetComponent<第三人称控制器>();
    // 停止角色移动
    characterController.isMovingDisabled = true;
    // 找到名为player_track的轨道
    var timeline = GameObject.FindObjectOfType<Timeline.TimelineAsset>();
    var director = gameObject.AddComponent<Timeline.TimelinePlayer>();
    director.Play(timeline);
    yield return new WaitForSeconds(pickUpTime);
    // 将物体设置到手上
    pickedObject.transform.SetParent(hand);
    pickedObject.transform.localPosition = Vector3.zero;
    pickedObject.transform.localRotation = Quaternion.identity;
    // 人物移动到站立目标点
    transform.position = playerStandPoint.position;
    transform.rotation = playerStandPoint.rotation;
    // 恢复角色移动
    characterController.isMovingDisabled = false;
    // 标记拾取完成
    isPickUpComplete = true;
}

四、在 Unity 中配置脚本

  1. 为玩家添加拾取能力:回到 Unity Editor,为玩家添加player_pick_up_ability脚本,将手部球体拖到 “hand” 属性上。
  2. 配置操作按键:若之前未添加过操作代码,找到 “Input” 组件,双击打开配置资产。删除原有的设置,重新点击添加 “Action”,更改名称为 “operate”。选择下面的绑定选项,在右侧绑定属性的 “patch” 中点击下拉菜单,输入 “F” 键确定绑定,勾选 “keyboard board” 选项,确保应用到键鼠方案,点击 “save asse” 保存资产。此时在 “behavior” 中会出现 “on operator” 的显示,表示按下 “F” 键时会触发脚本中同名函数。
  3. 为桌子添加拾取脚本:选择桌子物体,添加pick_up_object_on_table脚本,将需要拾取的物体拖动到 “object” 属性中,将站立点添加到对应的属性引用。根据动画文件适配拾取发生的时间。最后,将 “director” 中的唤醒(播放)勾选项去掉。

至此,我们就完成了在 Unity 中实现拾取物体到手上的交互功能。通过上述步骤,你可以用同样的方法实现拾取各种各样物体的交互功能。如果在实现过程中遇到问题,欢迎在评论区留言交流。希望大家多多点赞支持,后续我会带来更多有趣的游戏开发教程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值