我开发的升降梯由三个部分组成,反正适用于我的需求了,其他人想复用到自己的项目的话,不一定。写的也不是很好,感觉搞的有点复杂啦。完全可以在优化一下,项目赶工期,就先这样吧。能用就行,其他的再说。
1.升降梯基类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class LiftObjCtrBase : MonoBehaviour
{
public float speed = 5f; // 上升和下降的速度
public LiftObjCtrBase targetObject; // 指定的物体高度
[HideInInspector]
public bool isRising = false; // 是否正在上升
[HideInInspector]
public bool isFalling = false; // 是否正在下降
[HideInInspector]
public bool isPlayerStay = false; //玩家是否在上面
[HideInInspector]
public Vector3 initialPosition; // 初始位置
[HideInInspector]
public float offsetY = 0;
[HideInInspector]
public Transform playerTra;
[HideInInspector]
public Transform targetTra;
[HideInInspector]
public float radius = 0;
// Start is called before the first frame update
[HideInInspector]
public bool isReach = false;
public virtual bool isTriggerEnter(Transform playerTra) {
if (Vector3.Distance(gameObject.transform.position, playerTra.position) > radius)
{
return false;
}
else
{
return true;
}
}
public virtual void startRising() {
}
}
2.玩家接触到的头一个升降梯:第一个升降梯的碰撞组件,必须开启isTrigger属性;注意:所有升降梯都需要挂碰撞组件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.TextCore.Text;
public class LiftFirstObjCtr : LiftObjCtrBase
{
//private Transform player; // 角色
private void Start()
{
initialPosition = transform.position; // 记录初始位置
targetTra = targetObject.gameObject.transform;
MeshCollider meshCollider = gameObject.GetComponent<MeshCollider>();
radius = meshCollider.bounds.extents.magnitude;
}
private void Update()
{
if (targetObject == null) return;
if (playerTra != null && !isTriggerEnter(playerTra) && !isFalling)
{
isPlayerStay = false;
isFalling = true;
isRising = false;
}
if (playerTra !=null && targetObject.isTriggerEnter(playerTra) && !targetObject.isRising && !targetObject.isReach)
{
isPlayerStay = false;
isFalling = true;
targetObject.startRising();
}
if (isRising && isPlayerStay)
{
// 上升逻辑
if (playerTra == null || offsetY == 0) return;
transform.Translate(Vector3.up * speed * Time.deltaTime);
playerTra.position = new Vector3(playerTra.position.x, transform.position.y+ offsetY+0.4f, playerTra.position.z);
// 到达目标高度后开始下降
if (transform.position.y >= targetTra.position.y)
{
gameObject.GetComponent<Collider>().isTrigger = false;
isRising = false;
}
}
else if (isFalling && !isPlayerStay)
{
// 下降逻辑
transform.Translate(Vector3.down * speed * Time.deltaTime);
// 返回初始位置后停止下降
if (transform.position.y <= initialPosition.y)
{
transform.position = initialPosition;
isFalling = false;
gameObject.GetComponent<Collider>().isTrigger = true;
}
}
}
private void OnTriggerEnter(UnityEngine.Collider other)
{
if (other.gameObject.tag == "Player")
{
Debug.Log("玩家撞到升降梯");
}
}
public override bool isTriggerEnter(Transform playerTra) {
// 检测角色是否在碰撞器范围内
if (Vector3.Distance(gameObject.transform.position, playerTra.position) > radius)
{
return false;
}
else {
return true;
}
}
private void OnTriggerStay(UnityEngine.Collider other)
{
if (other.gameObject.tag == "Player" && !isPlayerStay)
{
if (Vector3.Distance(other.gameObject.transform.position, gameObject.transform.position)< radius) {
Debug.Log("玩家待在升降梯");
isRising = true;
playerFollow(other.gameObject);
gameObject.GetComponent<Collider>().isTrigger = false;
}
}
}
private void OnTriggerExit(UnityEngine.Collider other)
{
}
private void playerFollow(GameObject player) {
offsetY = player.transform.position.y - transform.position.y;
playerTra = player.transform;
isPlayerStay = true;
}
public override void startRising()
{
}
}
3.中间的其他升降梯,其他中间的升降梯由于是悬浮在空中的,所以需要不能开启isTrigger属性,否则玩家碰到后就会掉下去:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.TextCore.Text;
public class LiftMiddleObjCtr : LiftObjCtrBase
{
public LiftObjCtrBase preLiftObj;
// Update is called once per frame
private void Start()
{
initialPosition = transform.position; // 记录初始位置
targetTra = targetObject.transform;
MeshCollider meshCollider = gameObject.GetComponent<MeshCollider>();
radius = meshCollider.bounds.extents.magnitude;
}
void Update()
{
if (targetObject == null) return;
if (playerTra != null && !isTriggerEnter(playerTra) && !isFalling)
{
isPlayerStay = false;
isFalling = true;
isRising = false;
return;
}
if (playerTra != null && targetObject.isTriggerEnter(playerTra) && !targetObject.isRising)
{
isPlayerStay = false;
isFalling = true;
targetObject.startRising();
playerTra = null;
}
if (isRising && isPlayerStay)
{
// 上升逻辑
if (playerTra == null || offsetY == 0) return;
transform.Translate(Vector3.up * speed * Time.deltaTime);
playerTra.position = new Vector3(playerTra.position.x, transform.position.y + offsetY + 0.4f, playerTra.position.z);
// 到达目标高度后开始下降
if (transform.position.y >= targetTra.position.y)
{
isRising = false;
isReach = true;
}
}
else if (isFalling && !isPlayerStay)
{
// 下降逻辑
transform.Translate(Vector3.down * speed * Time.deltaTime);
// 返回初始位置后停止下降
if (transform.position.y <= initialPosition.y)
{
transform.position = initialPosition;
isFalling = false;
isReach = false;
isRising = false;
}
}
}
public override bool isTriggerEnter(Transform playerTra)
{
if (Vector3.Distance(gameObject.transform.position, playerTra.position) > radius)
{
return false;
}
else
{
return true;
}
}
public override void startRising() {
isRising = true;
playerFollow(preLiftObj.playerTra.gameObject);
gameObject.GetComponent<Collider>().isTrigger = false;
}
private void playerFollow(GameObject player)
{
offsetY = player.transform.position.y - transform.position.y;
playerTra = player.transform;
isPlayerStay = true;
}
}
4.最后一个升降梯,是玩家最终达到的升降梯,所以可以不用升降,他是出发倒数第二个升降梯的下降:感觉有点奇怪,反正整个组件都开发的感觉奇奇怪怪的,算了算了,咱也没啥要求,混口饭吃,能较差就行
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LiftLastObjCtr : LiftObjCtrBase
{
// Start is called before the first frame update
public LiftMiddleObjCtr middleObject;
public override bool isTriggerEnter(Transform playerTra)
{
return false;
}
public override void startRising()
{
}
// Update is called once per frame
void Update()
{
if (middleObject != null && middleObject.playerTra != null) {
if (Vector3.Distance(middleObject.playerTra.position,gameObject.transform.position) < 1) {
if (Vector3.Distance(middleObject.playerTra.position, middleObject.gameObject.transform.position) > 1)
{
middleObject.isFalling = true;
middleObject.isPlayerStay = false;
}
}
}
}
}