赞
踩
剧情中需要做什么?
1).创建物体
2).基础位移,旋转
3).UI控制
4).语音控制
等等…
命令类:
/// <summary>
/// 剧情命令基类
/// </summary>
public abstract class PlotCommand
{
/// <summary>
/// 剧情数据
/// </summary>
protected PlotInfo PlotInfo { get; set; }
/// <summary>
/// 上一条命令
/// </summary>
public PlotCommand PreCommand { get; set; }
/// <summary>
/// 下一条命令
/// </summary>
public PlotCommand NextCommand { get; set; }
/// <summary>
/// 解析
/// </summary>
/// <param name="plotInfo"></param>
/// <param name="command"></param>
/// <returns></returns>
public bool OnParse(PlotInfo plotInfo, string command)
{
PlotInfo = plotInfo;
return Parse(command);
}
/// <summary>
/// 解析
/// </summary>
/// <param name="command"></param>
/// <returns></returns>
public abstract bool Parse(string command);
/// <summary>
/// 执行
/// </summary>
/// <returns></returns>
public abstract bool DoAction();
/// <summary>
/// 命令结束
/// </summary>
protected void OnComandFinsh()
{
if (NextCommand != null)
NextCommand.DoAction();
else
PlotInfo.Close();
}
}
例如:
/// <summary>
/// 创建角色
/// </summary>
public class CreateActor : PlotCommand
{
public string ActorName;
public string ModelName;
public override bool DoAction()
{
Debug.Log(string.Format("创建角色:{0}-{1}",ActorName,ModelName));
PlotInfo.PlotManager.CreateActor(ActorName, ModelName);
OnComandFinsh();
return true;
}
public override bool Parse(string command)
{
string[] param = command.Split(',');
ActorName = param[0];
ModelName = param[1];
return true;
}
}
/// <summary>
/// 设置坐标
/// </summary>
public class SetPosition : PlotCommand
{
public string ActorName;
public Vector3 ActorPos;
public float Time;
public int type;
public override bool DoAction()
{
Debug.Log(string.Format("设置角色坐标:{0}-{1}", ActorName, ActorPos));
switch (type)
{
case 2:
PlotInfo.PlotManager.SetActorPos(ActorName, ActorPos);
break;
case 3:
PlotInfo.PlotManager.SetActorPos(ActorName, ActorPos,Time);
break;
}
OnComandFinsh();
return false;
}
public override bool Parse(string command)
{
string[] param = command.Split(',');
ActorName = param[0];
ActorPos = PlotTools.ParseVector3(param[1]);
type = 2;
if (param.Length > 2)
{
Time = float.Parse(param[2]);
type = 3;
}
return true;
}
}
/// <summary>
/// 设置旋转
/// </summary>
public class SetRotation : PlotCommand
{
public string ActorName;
public Vector3 Angle;
public float Speed;
public override bool DoAction()
{
Debug.Log(string.Format("设置角色转向:{0}-{1}", ActorName, Angle));
PlotInfo.PlotManager.SetActorRot(ActorName,Angle, Speed);
OnComandFinsh();
return true;
}
public override bool Parse(string command)
{
string[] param = command.Split(',');
ActorName = param[0];
string[] rot = param[1].Split('|');
Angle = PlotTools.ParseVector3(param[1]);
Speed = float.Parse(param[2]);
return true;
}
}
等等,可以进行其他命令扩展,比如UI,音效,以及延时命令等
//延时
public class Delay : PlotCommand
{
public float DelayTime;
public override bool DoAction()
{
Debug.Log(string.Format("延时:{0}", DelayTime));
PlotTools.Instance.Delay(DelayTime, delegate {
OnComandFinsh();
});
return false;
}
public override bool Parse(string command)
{
DelayTime = float.Parse(command);
return true;
}
}
创建一个工程用来生成命令
public class PlotFactory {
private static Hashtable lookUpType = new Hashtable();
public static PlotCommand Create(string name)
{
PlotCommand c = null;
try
{
var type = (Type)lookUpType[name];
lock (lookUpType)
{
if (type == null)
{
//Assembly curAssembly = Assembly.GetEntryAssembly();
type = Type.GetType(name);
//type = Type.GetType();
lookUpType[name] = type;
}
}
if (type != null)
c = Activator.CreateInstance(type) as PlotCommand;
}
catch (Exception ex)
{
Debug.Log( string.Format("创建剧情命令{0},失败!!",ex.Message));
}
return c;
}
}
剧情数据类:
using System.Collections.Generic;
public class PlotInfo
{
private List<PlotCommand> PlotCommands = new List<PlotCommand>();
public PlotInfo() { }
public PlotManager PlotManager { get; private set; }
public PlotInfo(PlotManager plotManager)
{
PlotManager = plotManager;
}
/// <summary>
/// 开始剧情
/// </summary>
public void Play()
{
PlotManager.ClearPlotActor();
if (Count > 0)
PlotCommands[0].DoAction();
}
/// <summary>
/// 停止剧情
/// </summary>
public void Stop()
{
}
/// <summary>
/// 关闭剧情
/// </summary>
public void Close()
{
}
public void AddCommand(PlotCommand PlotCommand)
{
if (Count > 0)
{
PlotCommand.PreCommand = PlotCommands[Count - 1];
PlotCommands[Count - 1].NextCommand = PlotCommand;
}
PlotCommands.Add(PlotCommand);
}
public int Count
{
get{ return PlotCommands.Count;}
}
}
写了一个实现接口
public interface IPlot {
//创建角色
void CreateActor(string name, string assetName);
//设置坐标
void SetActorPos(string name, Vector3 pos);
void SetActorPos(string name, Vector3 pos, float time);
void SetActorPos(int index, Vector3 pos);
void SetActorPos(int index, Vector3 pos, float time);
//设置旋转
void SetActorRot(string name, Vector3 Angle, float time);
void SetActorRot(int index, Vector3 Angle, float time);
void Play(string plotName);
}
管理类:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(PlotTools))]
public class PlotManager : MonoBehaviour, IPlot
{
private static PlotManager _instance;
public static PlotManager Instance
{
get
{
return _instance;
}
}
/// <summary>
/// 解析剧情
/// </summary>
/// <param name="command"></param>
/// <returns></returns>
public static PlotInfo ParsePlot(string command)
{
command = command.Replace("\r", "");
string[] commandAry = command.Split('\n');
PlotInfo pi = new PlotInfo(PlotManager.Instance);
for (int i = 0; i < commandAry.Length; i++)
{
if (commandAry[i].Equals("")) continue;
string[] commandStruct = commandAry[i].Split(':');
PlotCommand pc = PlotFactory.Create(commandStruct[0]);
if (pc != null)
{
pc.OnParse(pi,commandStruct[1]);
pi.AddCommand(pc);
}
else
Debug.Log(string.Format("创建剧情命令{0},失败!!", commandStruct[0]));
}
return pi;
}
/// <summary>
/// 解析剧情
/// </summary>
/// <param name="PlotId"></param>
/// <returns></returns>
public static PlotInfo ParsePlot(int PlotId)
{
return null;
}
public GameObject obj;
public TextAsset plot;
private Dictionary<string, GameObject> PlotActors = new Dictionary<string, GameObject>();
void Awake()
{
_instance = this;
}
void Start()
{
PlotInfo pi = ParsePlot(plot.text);
pi.Play();
}
/// <summary>
/// 创建角色
/// </summary>
/// <param name="name"></param>
/// <param name="assetName"></param>
public void CreateActor(string name, string assetName)
{
GameObject actor = GameObject.Instantiate(obj) as GameObject;
actor.transform.parent = this.transform;
actor.name = name;
PlotActors.Add(actor.name,actor);
}
/// <summary>
/// 设置角色位置
/// </summary>
/// <param name="name"></param>
/// <param name="pos"></param>
public void SetActorPos(string name, Vector3 pos)
{
GameObject actor = GetActor(name);
if (actor != null)
actor.transform.localPosition = pos;
}
/// <summary>
/// 设置角色位置 时间
/// </summary>
/// <param name="name"></param>
/// <param name="pos"></param>
/// <param name="time"></param>
public void SetActorPos(string name, Vector3 pos, float time)
{
MoveTick tick = new MoveTick();
tick.moveActor = GetActor(name).transform;
tick.moveEndPos = pos;
float dis = Vector3.Distance(tick.moveActor.localPosition, pos);
tick.moveSpeed = dis / time;
PlotTools.Instance.AddPlotTick(tick);
}
/// <summary>
/// 设置角色选择 速度
/// </summary>
/// <param name="name"></param>
/// <param name="Angle"></param>
/// <param name="speed"></param>
public void SetActorRot(string name, Vector3 Angle, float speed)
{
RotTick tick = new RotTick();
tick.rotActor = GetActor(name).transform;
tick.EndAngle = Angle;
tick.rotSpeed = speed;
PlotTools.Instance.AddPlotTick(tick);
}
/// <summary>
/// 获取角色
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public GameObject GetActor(string name)
{
if (PlotActors.ContainsKey(name))
return PlotActors[name];
return null;
}
/// <summary>
/// 获取角色
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public GameObject GetActor(int index)
{
//-1 表示为主角
if (index == -1)
{
//获取主角数据
return null;
}
if (PlotActors.Count > index)
{
List<GameObject> actor = new List<GameObject>(PlotActors.Values);
return actor[index];
}
return null;
}
/// <summary>
/// 清楚角色
/// </summary>
public void ClearPlotActor()
{
List<GameObject> obj = new List<GameObject>(PlotActors.Values);
for (int i = 0; i < obj.Count; i++)
{
Destroy(obj[i]);
}
PlotActors.Clear();
}
public void SetActorPos(int index, Vector3 pos)
{
throw new NotImplementedException();
}
public void SetActorPos(int index, Vector3 pos, float time)
{
throw new NotImplementedException();
}
public void SetActorRot(int index, Vector3 Angle, float time)
{
throw new NotImplementedException();
}
public void Play(string plotName)
{
throw new NotImplementedException();
}
}
循环方法,例如位移,旋转等需要没帧执行的
public abstract class PlotTick
{
public System.Action OnFinsh;
public bool IsFinsh { get; protected set; }
public abstract void OnUpdate();
}
public class MoveTick : PlotTick
{
public float moveSpeed;
public Vector3 moveEndPos;
public Transform moveActor;
public override void OnUpdate()
{
moveActor.localPosition = Vector3.MoveTowards(moveActor.localPosition, moveEndPos, moveSpeed * Time.deltaTime);
if (moveActor.localPosition == moveEndPos)
{
IsFinsh = true;
if (OnFinsh != null)
OnFinsh();
}
}
}
public class RotTick : PlotTick
{
public float rotSpeed;
public Vector3 EndAngle;
public Transform rotActor;
public override void OnUpdate()
{
rotActor.localEulerAngles = Vector3.Lerp(rotActor.localEulerAngles, EndAngle, rotSpeed * Time.deltaTime);
if (Vector3.Distance(rotActor.localEulerAngles,EndAngle)<0.02f)
{
IsFinsh = true;
if (OnFinsh != null)
OnFinsh();
}
}
}
工具类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlotTools : MonoBehaviour {
private static PlotTools _instance;
public static PlotTools Instance
{
get {
return _instance;
}
}
void Awake()
{
_instance = this;
}
void Start()
{
}
private List<PlotTick> plotTick = new List<PlotTick>();
private List<PlotTick> removePlotTick = new List<PlotTick>();
void Update()
{
removePlotTick.Clear();
for (int i = 0; i < plotTick.Count; i++)
{
if (!plotTick[i].IsFinsh)
{
plotTick[i].OnUpdate();
continue;
}
removePlotTick.Add(plotTick[i]);
}
for (int i = 0; i < removePlotTick.Count; i++)
{
RemovePlotTick(removePlotTick[i]);
}
}
public void AddPlotTick(PlotTick tick)
{
plotTick.Add(tick);
}
public void RemovePlotTick(PlotTick tick)
{
if(plotTick.Contains(tick))
plotTick.Remove(tick);
}
/// <summary>
/// 延时执行某个方法
/// </summary>
/// <param name="time"></param>
/// <param name="OnFinsh"></param>
public void Delay(float time, System.Action OnFinsh)
{
StartCoroutine(IeDelay(time, OnFinsh));
}
IEnumerator IeDelay(float time, System.Action OnFinsh)
{
yield return new WaitForSeconds(time);
if (OnFinsh != null)
OnFinsh();
}
public static Vector3 ParseVector3(string content)
{
string[] data = content.Split('|');
return new Vector3(float.Parse(data[0]), float.Parse(data[1]), float.Parse(data[2]));
}
public static Vector2 ParseVector2(string content)
{
string[] data = content.Split('|');
return new Vector2(float.Parse(data[0]), float.Parse(data[1]));
}
}
配置剧情:
最后需要将PlotManager和PlotTools脚本挂载到物体上
播放剧情,就是PlotManager中的Start方法
void Start()
{
PlotInfo pi = ParsePlot(plot.text);
pi.Play();
}
为了演示,我将创建物体,剧情读取都直接进行了面板拖拽的方式,在正式的项目中需要调用项目的中创建接口和资源接口。
后期扩展可以写个时间轴工具,添加事件等等。
最终实现创建、位移,旋转等操作
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。