一、轿厢实例说明
- 楼层信息获取----包括楼层名和在各楼层时轿厢的位置;
- 轿厢上下移动----判断当前位置与目标点的距离,通过距离的正负来决定移动方向;
- 对重移动----对重的移动取决于轿厢,同时与轿厢应保持速度相同和运动方向相反;
- 开关层门与轿厢门----根据轿厢的状态以及轿厢当前位置判断是否停靠在某一层,播放动画;
- 轿厢AI----根据情况自动调用以上各部分。
二、需求分析
1、轿厢移动
- 定义列表变量----楼层信息
- 轿厢运动状态判断及运行----上行、下行、停止
1>楼层信息
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StatusInfo : MonoBehaviour
{
public int people = 2;
public int maxPeople = 12;
public int amountPeople = 2;
public bool MovePeople()
{
int currentPeople = people + amountPeople;
if (people == 0 || currentPeople == people)
return false;
else if (currentPeople > maxPeople)
return false;
else
return true;
}
}
2>轿厢运动
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class Move : MonoBehaviour
{
public Transform[] points;
public WayLine line;
private int currentPointIndex=0;
public float MoveSpeed = 5;
public enum CarState
{
up,
down,
stop
}
public CarState carCurrentState = CarState.stop;
public CarState CarStateJudge(Vector3 point)
{
if (this.transform.position.y < point.y && (decimal)Vector3.Distance(this.transform.position, point) > 0.05m)
return carCurrentState = CarState.up;
else if (this.transform.position.y > point.y && (decimal)Vector3.Distance(this.transform.position, point) > 0.05m)
return carCurrentState = CarState.down;
else
return carCurrentState = CarState.stop;
}
public void CarMovement()
{
try
{
if (currentPointIndex < points.Length)
{
CarStateJudge(points[currentPointIndex].position);
switch (carCurrentState)
{
case CarState.up:
this.transform.Translate(0, MoveSpeed * Time.deltaTime, 0);
break;
case CarState.down:
this.transform.Translate(0, -MoveSpeed * Time.deltaTime, 0);
break;
case CarState.stop:
this.transform.Translate(0, 0, 0);
break;
}
}
}
catch { }
}
public bool Pathfinding()
{
if (points == null || currentPointIndex >= points.Length)
{
this.transform.Translate(0, 0, 0);
return false;
}
else
{
CarMovement();
if ((decimal)Vector3.Distance(this.transform.position, points[currentPointIndex].position) < 0.05m)
currentPointIndex++;
return true;
}
}
}
2、对重移动
- 对重移动与轿厢移动相反,同时要跟随轿厢移动
- 欠缺:只能将轿厢的位置放在最高,对重的位置放在最低,后期可能会想着将这两个对象的位置时刻关联(估计有难度)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CWMove : MonoBehaviour
{
public void CwMoveByCar(bool IsRun,Move carmove)
{
if (IsRun == true)
{
if (carmove.carCurrentState == Move.CarState.down)
{
this.transform.Translate(0,0, -carmove.MoveSpeed*3 * Time.deltaTime);
}
else if (carmove.carCurrentState == Move.CarState.up)
this.transform.Translate(0, 0,carmove.MoveSpeed *3* Time.deltaTime);
}
else
this.transform.Translate(0, 0, 0);
}
}
3、开关门动画
1>挂载到物体上的动画类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DoorAnimation : MonoBehaviour
{
public string[] BuildingDoor;
public Animations action;
private void Awake()
{
action = new Animations(GetComponentInChildren<Animation>());
}
}
2>普通C#动画类
- 目前遇到问题----如何将同一个动画正播后停止在最后一帧,在过几秒钟后将该动画倒播回去
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Animations
{
private Animation anim;
public Animations(Animation anim)
{
this.anim = anim;
}
public void Play(string animName)
{
anim.Play(animName);
}
public bool IsPlaying(string animName)
{
return anim.IsPlaying(animName);
}
}
4、轿厢AI
- 定义电梯状态信息----运动、停止、待机、检修
- 根据每个状态来定义各自实现的功能
- 运行过程如果到达目标层----状态改为停止
- 若不在规定的楼层停止----状态改为检修,在规定的楼层停止----播放开关门动画,没人后状态改为待机
- 若在待机过程中,目标位置发生改变----运行状态改为运动
- 欠缺:停止过程的动画只能播放一次(目前是倒播),DeBug过程他也能进去,但实际就是不管用,试了好几个函数都没用(气的暂停这步了)
- 欠缺:检修状态的事件暂时没想到
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(DoorAnimation))]
[RequireComponent(typeof(StatusInfo))]
public class CarAI : MonoBehaviour
{
public enum State
{
Run,
Stop,
Check,
Rest
}
private State currentState = State.Run;
private DoorAnimation anim;
private Move move;
private CWMove cw;
private FloorInfo floor;
private StatusInfo stf;
private void Start()
{
anim = GetComponent<DoorAnimation>();
move = GetComponentInChildren<Move>();
cw = GetComponentInChildren<CWMove>();
floor = GetComponentInChildren<FloorInfo>();
floor.AddFloor();
stf = GetComponent<StatusInfo>();
}
private void Update()
{
switch(currentState)
{
case State.Run:
Run();
break;
case State.Stop:
Stop();
break;
case State.Rest:
Rest();
break;
case State.Check:
Check();
break;
}
}
private void Stop()
{
bool IsStopOk = false;
int fl = 0;
foreach (KeyValuePair<int,Vector3>kv in floor.Floor)
{
if((decimal)Vector3.Distance(move.transform.position, kv.Value) < 0.05m)
{
if (kv.Key == -1)
{
anim.action.Play(anim.BuildingDoor[0]);
}
else
{
anim.action.Play(anim.BuildingDoor[kv.Key]);
fl = kv.Key;
}
IsStopOk = true;
break;
}
}
if(IsStopOk==true)
{
float i = 0;
while (true)
{
i += Time.deltaTime;
if (i >= 2 && stf.MovePeople() == false)
{
anim.action.Close(anim.BuildingDoor[fl]);
currentState = State.Rest;
break;
}
}
}
else
{
currentState = State.Check;
}
}
private void Run()
{
move.Pathfinding();
cw.CwMoveByCar(move.Pathfinding(), move);
if (move.Pathfinding() == false) currentState = State.Stop;
}
private void Rest()
{
move.carCurrentState = Move.CarState.stop;
move.CarMovement();
if (move.CarStateJudge(move.points[0].position) != Move.CarState.stop)
currentState = State.Run;
}
private void Check()
{
}
}
三、效果图
- 整体缺陷:
1、使用Translate进行移动,会存在到了指定楼层后一直上下抖动的情况,导致动画不播放(其实把判断的距离设大就行,但是看起来就不贴合实际了) 2、同一个动画的正播和反播问题 3、初步想法,后期有待完善
|