简易的门制作
对于一个新手来说,这个工具是最好的选择
上一篇关于开关门的文章相对于复杂,感兴趣的可以查看上篇开关门制作
优点
- 挂载就能使用
- 控制面板一看就懂(全是中文)
- 简单的调试就能获得自己想要的效果
- 易懂且易修改的代码
面板
参数
- 锁:勾选后不能对门进行操作
- 声音:激活时自动播放
- 激活:测试开关门
- 查看结果位置:按住查看结果,松开返回
旋转门的使用不做介绍
推拉门(推拉抽屉):
- 起始位置:门的初始位置
- 结束位置:门要移动的位置
- 得到位置按钮:当你在场景中调整门的位置后,把当前门的位置赋值到左侧
代码
挂载之后会自动添加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了,按照流程赋值粘贴代码就能用 !