当前位置:网站首页>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了,按照流程赋值粘贴代码就能用 !
边栏推荐
- Face_recognition人脸识别之考勤统计
- Wuzhicms code audit
- Why are some online concerts always weird?
- [HCIA continuous update] WLAN overview and basic concepts
- Introduction of time related knowledge in kernel
- 【Hot100】32. Longest valid bracket
- You should know something about ci/cd
- With the stock price plummeting and the market value shrinking, Naixue launched a virtual stock, which was deeply in dispute
- 表情包坑惨职场人
- Redis主从复制
猜你喜欢

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"

Superscalar processor design yaoyongbin Chapter 7 register rename excerpt

使用3DMAX制作一枚手雷
Blood spitting finishing nanny level series tutorial - play Fiddler bag grabbing tutorial (2) - first meet fiddler, let you have a rational understanding

What is low code development?

"In Vietnam, money is like lying on the street"

Superscalar processor design yaoyongbin Chapter 6 instruction decoding excerpt

Numpy 的仿制 2

爬虫初级学习

就在今天丨汇丰4位专家齐聚,共讨银行核心系统改造、迁移、重构难题
随机推荐
LD_LIBRARY_PATH 环境变量设置
mysql5.7安装教程图文详解
[proteus simulation] printf debugging output example based on VSM serial port
华为云ModelArts的使用教程(附详细图解)
[daily question] 556 Next bigger element III
简单易用的地图可视化
What if Kaili can't input Chinese???
Face_recognition人脸识别之考勤统计
Wuzhicms code audit
78岁华科教授冲击IPO,丰年资本有望斩获数十倍回报
Vscode modification indentation failed, indent four spaces as soon as it is saved
celebrate! Kelan sundb and Zhongchuang software complete the compatibility adaptation of seven products
【系统分析师之路】第七章 复盘系统设计(结构化开发方法)
股价大跌、市值缩水,奈雪推出虚拟股票,深陷擦边球争议
[HCIA continuous update] WLAN overview and basic concepts
[system analyst's road] Chapter 7 double disk system design (structured development method)
Is it science or metaphysics to rename a listed company?
创业两年,一家小VC的自我反思
Electronic pet dog - what is the internal structure?
2022年DCMM认证全国各地补贴政策汇总