当前位置:网站首页>Unity 制作旋转门 推拉门 柜门 抽屉 点击自动开门效果 开关门自动播放音效 (附带编辑器扩展代码)
Unity 制作旋转门 推拉门 柜门 抽屉 点击自动开门效果 开关门自动播放音效 (附带编辑器扩展代码)
2022-07-04 16:17:00 【唐沢】
简易的门制作
对于一个新手来说,这个工具是最好的选择
上一篇关于开关门的文章相对于复杂,感兴趣的可以查看上篇开关门制作
优点
- 挂载就能使用
- 控制面板一看就懂(全是中文)
- 简单的调试就能获得自己想要的效果
- 易懂且易修改的代码
面板
参数
- 锁:勾选后不能对门进行操作
- 声音:激活时自动播放
- 激活:测试开关门
- 查看结果位置:按住查看结果,松开返回
旋转门的使用不做介绍
推拉门(推拉抽屉):
- 起始位置:门的初始位置
- 结束位置:门要移动的位置
- 得到位置按钮:当你在场景中调整门的位置后,把当前门的位置赋值到左侧
代码
挂载之后会自动添加Audio Source组件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(AudioSource))]
public class Door_Interaction : MonoBehaviour
{
public enum doorType {
RotatingDoor = 0, SlidingDoor = 1 }
public doorType doorMovementType;
public bool open;
public bool locked;
public float rotateAngle = 90;
public float speed = 1;
public enum axis {
X = 0, Y = 1, Z = 2 }
public axis rotateAxis = axis.Y;
public Vector3 startingPosition;
public Vector3 endingPosition;
public AudioClip startClip;
public AudioClip endClip;
private AudioSource sound;
public Quaternion originRotation;
public Quaternion openRotation;
private float r;
private bool opening;
[Tooltip("激活测试")]
public bool activate = false;
void Start()
{
InitRotation();
sound = GetComponent<AudioSource>();
r = 0;
}
public void InitRotation()
{
originRotation = transform.rotation;
openRotation = originRotation;
if (rotateAxis == axis.Y)
{
openRotation = Quaternion.Euler(new Vector3(originRotation.eulerAngles.x, originRotation.eulerAngles.y + rotateAngle, originRotation.eulerAngles.z));
}
else if (rotateAxis == axis.X)
{
openRotation = Quaternion.Euler(new Vector3(originRotation.eulerAngles.x + rotateAngle, originRotation.eulerAngles.y, originRotation.eulerAngles.z));
}
else if (rotateAxis == axis.Z)
{
openRotation = Quaternion.Euler(new Vector3(originRotation.eulerAngles.x, originRotation.eulerAngles.y, originRotation.eulerAngles.z + rotateAngle));
}
}
void Update()
{
if (activate)
{
activate = false;
if (opening == false && locked == false)
{
open = !open;
r = 0;
opening = true;
}
}
if (opening)
{
ChangeState(open);
}
}
void ChangeState(bool State)
{
Quaternion quaternion;
Vector3 vector3;
if (State)
{
quaternion = openRotation;
vector3 = endingPosition;
if (startClip!=null&& r==0)
{
sound.clip = startClip;
sound.Play();
}
}
else
{
quaternion = originRotation;
vector3 = startingPosition;
if (endClip != null && r == 0)
{
sound.clip = endClip;
sound.Play();
}
}
r += Time.deltaTime * speed;
if (doorMovementType == doorType.RotatingDoor)
{
if (Quaternion.Angle(quaternion, transform.rotation) > 0.1F)
{
transform.rotation = Quaternion.Slerp(transform.rotation, quaternion, r);
}
else
{
transform.rotation = quaternion;
r = 0;
opening = false;
}
}
else if (doorMovementType == doorType.SlidingDoor)
{
if (Vector3.Distance(transform.localPosition, vector3) > 0.005F)
{
transform.localPosition = Vector3.Lerp(transform.localPosition, vector3, r);
}
else
{
transform.localPosition = vector3;
r = 0;
opening = false;
}
}
}
}
编辑器扩展代码
需要注意!这个代码必须放在Editor文件下才能正常使用,Unity会自己处理Editor文件夹,就像Resources文件夹一样
我之前写的通用相机控制器也是一样的使用方法
感兴趣的可以查看通用相机控制器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(Door_Interaction)), CanEditMultipleObjects]
public class Door_Interaction_Editor : Editor
{
private SerializedProperty open;
private SerializedProperty locked;
private SerializedProperty rotateAngle;
private SerializedProperty speed;
private SerializedProperty rotateAxis;
private SerializedProperty startingPosition;
private SerializedProperty endingPosition;
private SerializedProperty activate;
private SerializedProperty startClip;
private SerializedProperty endClip;
private GUIStyle defaultStyle = new GUIStyle();
public void OnEnable()
{
open = serializedObject.FindProperty("open");
locked = serializedObject.FindProperty("locked");
rotateAngle = serializedObject.FindProperty("rotateAngle");
speed = serializedObject.FindProperty("speed");
rotateAxis = serializedObject.FindProperty("rotateAxis");
startingPosition = serializedObject.FindProperty("startingPosition");
endingPosition = serializedObject.FindProperty("endingPosition");
activate = serializedObject.FindProperty("activate");
startClip = serializedObject.FindProperty("startClip");
endClip = serializedObject.FindProperty("endClip");
}
bool IsButtonDown = false;
Vector3 CurrentPosition= Vector3.zero;
Quaternion CurrentRotation = Quaternion.identity;
public override void OnInspectorGUI()
{
serializedObject.Update();
var myScript = target as Door_Interaction;
var doorGUIContent = new GUIContent("门类型", "选择不同门的类型参数也有所改变");
GUIContent[] doorOptions;
doorOptions = new[] {
new GUIContent("旋转门"), new GUIContent("推拉门") };
myScript.doorMovementType = (Door_Interaction.doorType)EditorGUILayout.Popup(doorGUIContent, (int)myScript.doorMovementType, doorOptions);
EditorGUILayout.PropertyField(open,new GUIContent("当前状态"));
EditorGUILayout.PropertyField(locked, new GUIContent("锁"));
EditorGUILayout.PropertyField(speed, new GUIContent("执行速度"));
EditorGUILayout.PropertyField(startClip, new GUIContent("打开时的声音"));
EditorGUILayout.PropertyField(endClip, new GUIContent("关闭时的声音"));
EditorGUILayout.PropertyField(activate, new GUIContent("激活"));
GUILayout.Space(20);//间隔
if (myScript.doorMovementType == Door_Interaction.doorType.RotatingDoor) {
EditorGUILayout.PropertyField(rotateAngle, new GUIContent("旋转角度"));
EditorGUILayout.PropertyField(rotateAxis, new GUIContent("轴", "门的旋转轴。 默认是Y "));
GUILayout.Space(20);//间隔
if (GUILayout.RepeatButton(new GUIContent("查看结束位置", "在视图中查看结束位置")))
{
if (IsButtonDown == false)
{
IsButtonDown = true;
myScript.InitRotation();
CurrentRotation = myScript.transform.localRotation;
}
myScript.transform.rotation = myScript.openRotation;
}
else
{
if (IsButtonDown)
{
IsButtonDown = false;
myScript.transform.localRotation = CurrentRotation;
}
}
} else if (myScript.doorMovementType == Door_Interaction.doorType.SlidingDoor) {
defaultStyle.alignment = TextAnchor.UpperCenter; //字体对齐方式: 水平靠左,垂直居中
defaultStyle.normal.textColor = Color.yellow; //字体颜色:黄色
defaultStyle.fontSize = 15; //字体大小: 20
GUILayout.Label("起始位置", defaultStyle);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(startingPosition, new GUIContent(""));
if (GUILayout.Button(new GUIContent("得到位置", "将当前的局部坐标赋值给开始位置")))
{
myScript.startingPosition = myScript.transform.localPosition;
}
EditorGUILayout.EndHorizontal();
GUILayout.Label("结束位置", defaultStyle);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(endingPosition, new GUIContent(""));
if (GUILayout.Button(new GUIContent("得到位置", "将当前的局部坐标赋值给结束位置")))
{
myScript.endingPosition = myScript.transform.localPosition;
}
EditorGUILayout.EndHorizontal();
GUILayout.Space(20);//间隔
if (GUILayout.RepeatButton(new GUIContent("查看结束位置", "在视图中查看结束位置")))
{
if (IsButtonDown==false)
{
IsButtonDown = true;
CurrentPosition = myScript.transform.localPosition;
}
myScript.transform.localPosition = myScript.endingPosition;
}
else
{
if (IsButtonDown)
{
IsButtonDown = false;
myScript.transform.localPosition = CurrentPosition;
}
}
}
serializedObject.ApplyModifiedProperties();//顾名思义 应用修改的属性
if (GUI.changed == true) {
EditorUtility.SetDirty(target);//这个函数告诉引擎,相关对象所属于的Prefab已经发生了更改。
}
}
}
别要Demo了,按照流程赋值粘贴代码就能用 !
边栏推荐
- Offline and open source version of notation -- comprehensive evaluation of note taking software anytype
- Perfectly integrated into win11 style, Microsoft's new onedrive client is the first to see
- Superscalar processor design yaoyongbin Chapter 6 instruction decoding excerpt
- 股价大跌、市值缩水,奈雪推出虚拟股票,深陷擦边球争议
- Why are some online concerts always weird?
- Five thousand words to clarify team self-organization construction | Liga wonderful talk
- 俄罗斯 Arenadata 发布基于PostgreSQL的产品
- 用于图数据库的开源 PostgreSQL 扩展 AGE被宣布为 Apache 软件基金会顶级项目
- [HCIA continuous update] overview of WLAN workflow
- 【209】go语言的学习思想
猜你喜欢
ISO27001认证办理流程及2022年补贴政策汇总
估值900亿,超级芯片IPO来了
【HCIA持续更新】WLAN工作流程概述
五千字讲清楚团队自组织建设 | Liga 妙谈
华为云ModelArts的使用教程(附详细图解)
DB-Engines 2022年7月数据库排行榜:Microsoft SQL Server 大涨,Oracle 大跌
Hidden corners of coder Edition: five things that developers hate most
补能的争议路线:快充会走向大一统吗?
What is low code development?
ISO27001 certification process and 2022 subsidy policy summary
随机推荐
用于图数据库的开源 PostgreSQL 扩展 AGE被宣布为 Apache 软件基金会顶级项目
The Block:USDD增长势头强劲
Vscode modification indentation failed, indent four spaces as soon as it is saved
Pytorch深度学习之环境搭建
Is BigDecimal safe to calculate the amount? Look at these five pits~~
解决el-input输入框.number数字输入问题,去掉type=“number“后面箭头问题也可以用这种方法代替
[system analyst's road] Chapter 7 double disk system design (structured development method)
Rainfall warning broadcast automatic data platform bwii broadcast warning monitor
To sort out messy header files, I use include what you use
[proteus simulation] printf debugging output example based on VSM serial port
90后开始攒钱植发,又一个IPO来了
shell脚本的替换功能实现
【211】go 处理excel的库的详细文档
Five thousand words to clarify team self-organization construction | Liga wonderful talk
Flask lightweight web framework
Developers, MySQL column finish, help you easily from installation to entry
Solve the El input input box For number number input problem, this method can also be used to replace the problem of removing the arrow after type= "number"
Interpretation of data security governance capability evaluation framework 2.0, the fourth batch of DSG evaluation collection
【HCIA持续更新】广域网技术
With an annual income of more than 8 million, he has five full-time jobs. He still has time to play games