学习目标:
提示:内容学习视频来源:B站
例如:
- 理解与运用C#中的事件
事件的五要素:
本期代码对应 - 1.拥有事件的类 --EventSystem
2.事件的响应者 --Door
3.事件 --OnDoorEnter,OnDoorExit
4.事件的订阅 +=DoorOpen,+=DoorClose
5.事件处理器 方法
学习内容:
自动门
1.在开始前需要准备一个新场景,并且创建一个空物体存放触发碰撞体(BoxCollider组件),并将其碰撞体的IsTriger勾选
2.代码部分与准备:加入LeanTween插件
3.代码部分:
Door
using UnityEngine;
public class Door:MonoBehaviour
{
[SerializeField] private int doorID;//记录ID,为游戏对象与触碰的门单独触发
[SerializeField] private float MoveHeith = 3.7f;//门的移动高度,这里可以根据场所自定意
[SerializeField] private float StartPos;
pulic void Start()//订阅事件
{
EventSystem.instance.OnDoorEnter += DoorOpen;
EventSystem.instance.OnDoorExit += DoorClose;
}
private viod OnDestory() //取消订阅,这里是扩展需求如果需要破坏门
{
EventSystem.instance.OnDoorEnter -= DoorOpen;
EventSystem.instance.OnDoorExit -= DoorClose;
}
//如果两个事件的处理器方法订阅事件的话,那么他们的返回值和参数列表,必须保持“类型兼容”
//事件是使用的Action的委托,我们的这两个方法,返回值必须为空,参数列表为空
public void DoorOpen(int _id )
{
if(doorID = _id)
LeanTween.moveLocalY(gameObject,MoveHeith,1.0f); //这里使用LeanTween插件
}
public void DoorClose(int _id)
{
if(doorID = _id)
LeanTween.moveLocalY(gameObject,StartPos,1.0f);
}
}
EventSystem代码:
using System;
using UnityEngine;
//事件的拥有者 ——EventSystem
public class EventSystem :MonoBehaviour
{
public static EventSystem instance;
private void Awake() //单例
{
if(instance == null)
{
instance =this;
}
if(instance != null)
{
Destory(gameObject);
}
DontDestoryOnLoad(gameObject);
}
//声明事件
public event Action<int> OnDoorEnter;
public event Action<int> OnDoorExit;
//事件外部是不能被直接调用的,是事件的拥有者的某些“内部逻辑”触发的
public void OpenDoor(int _id)
{
if(OnDoorEnter != null)
{
OnDoorEnter(_id);
}
}
public void CloseDoor(int _id)
{
if (OnDoorExit != null)
{
OnDoorExit(_id);
}
}
}
TriggerArea脚本:
using UnityEngine;
public class TriggerArea : MonoBehaviour
{
[SerializeField] private int AreaId;
private void OnTriggerEnter(Collider other)
{
EventSystem.instance.OpenDoor(AreaId);
}
private void OnTriggerExit(Collider other)
{
EvenSystem.instance.CloseDoor(AreaId);
}
}
PlayerMovement脚本:
using UnityEngine;
[requireComponent(typeof(Rigibody))]
public class PlayerMovement : MonoBehaviour
{
public Rigibody rb;
public float moveSpeed;
private Vector3 moveInput;
private void Start()
{
rb = GetComponent<Rigibody>();
}
private void Update()
{
moveInput = new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical"));
LookAtCursor();
}
private void LookAtCursor()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Plane plane = new Plane(Vector3.up, Vector3.zero);
float distToGround = 0;
if(plane.Raycast(ray, out distToGround))
{
Vector3 point = ray.GetPoint(distToGround);
Vector3 rightPoint = new Vector3(point.x, transform.position.y, point.z);
transform.LookAt(rightPoint);
}
private void FixedUpdate()
{
rb.MovePosition(rb.position + moveInput * moveSpeed * Time.deltaTime);
}
}
如果你还想控制门的不同的开门方向,可以如下书写
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//事件的响应者:Door
//事件的处理器:DoorOpen() DoorClose()
public enum Direction
{
AxisX, AxisY, AxisZ
}
public class Door : MonoBehaviour
{
[SerializeField] private float toAmount, oriAmount;
[SerializeField] private int doorID;
[SerializeField] private float MoveHeith = 3.7f;
public Direction direction; //方向AxisX, AxisY, AxisZ
private void Start()
{
EventSystem.instance.OnDoorEnter += DoorOpen;
EventSystem.instance.OnDoorExit += DoorClose;
}
private void OnDestroy()
{
EventSystem.instance.OnDoorEnter -= DoorOpen;
EventSystem.instance.OnDoorExit -= DoorClose;
}
//如果两个事件的处理器方法订阅事件的话,那么他们的返回值和参数列表,必须保持“类型兼容”
//事件是使用的Action的委托,我们的这两个方法,返回值必须为空,参数列表为空
public void DoorOpen(int _id)
{
if (doorID == _id)
// LeanTween.moveLocalY(gameObject, MoveHeith, 1.0f);
switch (direction)
{
case Direction.AxisX:
LeanTween.moveLocalX(gameObject, toAmount, 1.0f).setEaseInQuad();
break;
case Direction.AxisY:
LeanTween.moveLocalY(gameObject,toAmount, 1.0f).setEaseOutQuad();
break;
case Direction.AxisZ:
LeanTween.moveLocalZ(gameObject, toAmount, 1.0f).setEaseOutQuad();
break;
//}
}
public void DoorClose(int _id)
{
if(doorID == _id)
//LeanTween.moveLocalY(gameObject, 1.25f, 1.0f);
switch (direction)
{
case Direction.AxisX:
LeanTween.moveLocalX(gameObject, oriAmount, 1.0f).setEaseInQuad();
break;
case Direction.AxisY:
LeanTween.moveLocalY(gameObject, oriAmount, 1.0f).setEaseOutQuad();
break;
case Direction.AxisZ:
LeanTween.moveLocalZ(gameObject, oriAmount, 1.0f).setEaseOutQuad();
break;
}
}
}
Thank~