当前位置:   article > 正文

Unity3d 实现简单的剧情系统_unity 剧情配置 工作

unity 剧情配置 工作

剧情中需要做什么?
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();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

例如:

/// <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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93

等等,可以进行其他命令扩展,比如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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

创建一个工程用来生成命令


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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

剧情数据类:

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;}
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

写了一个实现接口

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);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

管理类:

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();
    }
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195

循环方法,例如位移,旋转等需要没帧执行的

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();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

工具类:

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]));
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87

配置剧情:

这里写图片描述

最后需要将PlotManager和PlotTools脚本挂载到物体上
这里写图片描述

播放剧情,就是PlotManager中的Start方法

   void Start()
    {
        PlotInfo pi = ParsePlot(plot.text);
        pi.Play();
    }
  • 1
  • 2
  • 3
  • 4
  • 5

为了演示,我将创建物体,剧情读取都直接进行了面板拖拽的方式,在正式的项目中需要调用项目的中创建接口和资源接口。

后期扩展可以写个时间轴工具,添加事件等等。
最终实现创建、位移,旋转等操作

这里写图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/98045
推荐阅读
相关标签
  

闽ICP备14008679号