【教程】使用 Unity 制作 “交互门“ 思路

本文介绍了在Unity中创建交互门的思路,包括自动、手动和物理触发三种类型的门。重点讨论了使用动画和物理系统实现门的交互,并详细阐述了如何通过Collider和Raycast进行范围检测和射线检测,以控制门的开启和关闭。同时,文章提到了代码优化和设计模式在减少冗余中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文目标:提供 “交互门” 制作思路,对开发中存在的问题给出解答参考。

开发平台:Unity 2018版本以上
编程语言:CSharp 6.0

一、阅读前须知


你必须了解以下内容,以高效率理解 “交互门” 设计思路。

  • Unity Animator & Animation 动画系统 | 组件及工具视窗使用
  • Unity Physics 物理系统
  • Basic CSharp 基础编程语法

—【若文章有遗漏或错误知识,请及时通知博主更新纠正】—

二、交互门的表现形式


分类描述案例附注
自动判定条件 集中于 “门” 的交互项感电门 + 感应门参考《Contain Breach》
手动偏向于以传递 “媒介” 触发交互门动作密码门 + 权限门参考《Black Mesa》
物理以 “玩家” 直接接触的交互行为参考《Human Fallen》

三、实践


  开发上倾向于使用 “动画” 形式进行门的表现。关于 ”物理门“ 可查阅网络文章配置 Physics 组件 —— 方向 Physics 系统下的 > Joint (关节)组件实现效果。下面主要围绕 “动画” 表现讨论:

3.1 如何通知门该表现其正确的


  即使面前摆放着一套带有 开、关,甚至被破坏的完整动画。让其正确的表现成为重中之重。如下所示:大致有两种方式。

应用对象流程
范围检测集中于 动画门 自身检测范围内对象是否满足条件,并给予反馈
射线检测集中于 玩家群 自身由玩家主动探寻对象,传递 “媒介” 等待门反馈

参考示意图:

图1 使用 Collider.isTrigger
图2 使用 Physics.RayCastHit

3.2 关于 范围检测


围绕 “碰撞器” 进行设计。根据其具有的 “触发器” 特性,检测区域内谁进出并予以对应反馈。例如:

public class DoorAccess : MonoBehaviour
{
	public void OnTriggerEnter(Collider other)
	{
		bool isGet = other.gameObject.TryGetComponet(out PlayerInfo output);
		if (isGet)
		{
			if(output.Role == RoleType.Human)
				Debug.Log("许可进入|播放开门动画");
		}
	}
}

  如上所示,我要求门在区域检测对象上必须挂载有 PlayerInfo.cs 组件,该组件提供 Role 属性可读,许可 RoleType.Human 的玩家可以触发开门动作。同理我们也可以在 OnTriggerExit 作出对应的关门逻辑。

  事实上,在丰富门的触发条件上,并非把所有条件写于方法内。可以了解一些设计模式降低代码冗余。


关于 Collider 说明

图1 Box Collider
图2 Mesh Collider
图2 Sphere Collider
图2 Capsule Collider
  • Collider 是一个 碰撞器基类。Unity 以此提供 Box|Mesh|Sphere|Capsule Collider 组件。
  • Collider.IsTrigger 需要被检测对象挂在 Collider 组件时可 Trigger 识别

关联CSharp API

public void OnTriggerEnter | 进入触发器 仅执行一次
public void OnTriggerStay  | 在触发器内 每帧执行一次 (可理解持续执行)
public void OnTriggerExit  | 离开触发器 仅执行一次

注意:为保证性能最优,使用 OnTriggerEnter & OnTriggerExit 即可。(获取玩家进出一刻的信息)

3.3 关于 射线检测


围绕 Physics.RayCastHIt 进行设计。由射线碰撞返回对象,执行对应逻辑动画。为保证准确性,一般情况下以 玩家主相机(Main Camera)组件作为射线发射原点。

public void Update()
{
	if(Input.GetKeyDown(KeyCode.E))
	{
		Ray cameraRay = Camera.main.ScreenPointToRay(new Vector2(Screen.Width/2, Screen.Height/2));
		bool isRay = Physics.Raycast(cameraRay, out RaycastHit hit);
		if (isRay)
		{
			// 获取对象管理 "交互门" 状态的脚本
			// 通知状态改变
		}
	}
}
  • 注意:上述为玩家主观触发,通过按键E触发操作。
  • 示例代码存在过渡性能浪费,仅用于参考理解思路。详细性能优化可参考学习网络文章。

射线检测 也可以用于设置信息状态显示,例如:约定射线有效距离。在该距离内,呈现 交互UI 提示可交互。即:

public void Update()
{
	Ray cameraRay = Camera.main.ScreenPointToRay(new Vector2(Screen.Width/2, Screen.Height/2));
	bool isRay = Physics.Raycast(cameraRay, out RaycastHit hit);
	if(isRay)
	{
		// 通知射线管理中心,处理反馈对应的 交互UI提醒
		// ......

		// 检查
		if (Input.GetKeyDown(KeyCode.E))
		{
			// 执行效果
		}
	}
}
  • 同上,代码存在性能损耗与设计非最佳。仅供参考。
关联UnityAPI【C#语言】有:
UnityAPI说明
Physics类全局物理属性和物理方法
Raycast投射光线,从点开始向一个方向投射一定长度,与有碰撞器的物体相撞
RaycastHit返回射线碰撞信息(需要对象有碰撞器)

小结


  找个时间把这篇远古文章润润。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值