自用Unity剧情系统

主要展示剧情部分

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class TextViewer : PlotTexts
{
  public GameObject PlotShower,PlotChooser;
  public Image CG;
  public Text Name, Talk;

  private void Awake()
  {

  }

  private void Update()
  {
    if (Plots.Count>0)
    {
      PlotShower.SetActive(true);
      Ploting();
    }
    else
    {
      PlotShower.SetActive(false);
    }
  }

  public void Ploting()
  { 
    Debug.Log(Plots.Count);
    CG.sprite = Plots[0].TalkCg;
    Name.text = Plots[0].Name;
    Talk.text = Plots[0].Say;
    if (Plots.Count>0&&Plots[0].PlotEvent==0)
    {    
      PlotChooser.SetActive(false);
      if (Input.GetMouseButtonDown(0))
      {
        Plots.RemoveAt(0);
      }
    }
    else if (Plots[0].PlotEvent!=0)
    {
      PlotEvents(Plots[0].PlotEvent);
    }

   
  }

  public void PlotEvents(int index)
  {
    Choose('A').onClick.RemoveAllListeners();
    Choose('B').onClick.RemoveAllListeners();
    
    switch (index)
    {
      case 1:
        PlotChooser.SetActive(true);
      Choose('A').onClick.AddListener(() =>
        {
          Plots.RemoveAt(0);
          SceneManager.LoadScene("Battle");
        
        });
        Choose('B').onClick.AddListener(() =>
        {
          Plots.RemoveAt(0);
          Plots.Add(new Plot(){PlotEvent = 0,Say = "测试剧情选项B",Name = "测试人"});
          Plots.Add(new Plot(){PlotEvent = 0,Say = "测试剧情选项B第二句",Name = "测试人"});
         
        });
        break;
      case -1:
      {
        if (Input.GetMouseButtonDown(0))
        {
          Plots.RemoveAt(0);
          SceneManager.LoadScene("Main");
        }
      }
        break;
      case -2:
      {
        if (Input.GetMouseButtonDown(0))
        { Plots.RemoveAt(0);
          SceneManager.LoadScene("Main");
        }
      }
        break;
    }

    Button Choose(char finder)
    {
      if (finder=='A')
      {
        return PlotChooser.transform.Find("A").GetComponent<Button>();
      }
      else
      {
        return PlotChooser.transform.Find("B").GetComponent<Button>();
      }
    }
  }


}

剧本存储部分

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlotTexts : MonoBehaviour
{
    public struct Plot
    {
        public int PlotEvent;
        public string Say;
        public string Name;
        public Sprite TalkCg;
   
    }
      
    public static List<Plot> Plots=new List<Plot>();

    public static void PlotAdder(int index)
    {
        switch (index)
        {
            case 1:    Plots.Add(new Plot(){PlotEvent = 0,Say = "测试剧情1",Name = "测试人"});
                Plots.Add(new Plot(){PlotEvent = 0,Say = "测试剧情2",Name = "测试人"});
                Plots.Add(new Plot(){PlotEvent = 1,Say = "测试剧情3",Name = "测试人"});
                break;
            case 2:
                Plots.Add(new Plot(){PlotEvent = 0,Say = "AA",Name = "主角"});
                Plots.Add(new Plot(){PlotEvent = 0,Say = "BB",Name = "对方"});
                break;
            case -1:
                Plots.Add(new Plot(){PlotEvent = 0,Say ="战败第一句",Name = "主角"});
                Plots.Add(new Plot(){PlotEvent = -1,Say ="战败第2句",Name = "主角"});
                break;
            case -2:
                Plots.Add(new Plot(){PlotEvent = 0,Say ="战胜第一句",Name = "主角"});
                Plots.Add(new Plot(){PlotEvent = -2,Say ="战胜第二句",Name = "主角"});
                break;
        }
    }

}

最终效果

 第二种,类似文字游戏的,用lua支持

控制按钮的

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using XLua;

[CSharpCallLua]
public class ButtonEvent : MonoBehaviour
{
    public Button[] Buttons;
    public Text ShowPort;//文本框
    public Image ShowIMG;//展示立绘
    public Sprite[] Sprites;//备选图集
    private bool IsBattle;
    
   // [CSharpCallLua]
  //  public delegate void LuaBtnEvent(int index);
    
    //[CSharpCallLua]
   // public static LuaBtnEvent BtnEvent;//被LuaModer引用
    private void OnEnable()
    {
        BTNSetEvent(0);
    }

    public void BTNSetEvent(int index)
    {
        ResetBTN();
        if (index==0)
        {

                ShowPort.text += "\n开始";
                BtnText(0).text = "开始游戏";
                GetBTN(0).onClick.AddListener(()=>BTNSetEvent(1));

        }
        else
        {
            if (PlotEvent.Plots[index].Specail)
            {
                LuaModer.luaEnv.DoString($"main.PlotEventBar({index})");
            }
            
            
            ShowPort.text += "\n" + PlotEvent.Plots[index].Plot;
            if (PlotEvent.Plots[index].Branch)
            {
                for (int i = 0; i < PlotEvent.Plots[index].BranchPlot.Length; i++)
                {
                    int i1 = i;
                    BtnText(i1).text = $"选择{(i1+1).ToString()}";//从0开始不符合玩家习惯
                    GetBTN(i1).onClick.AddListener(() =>
                    {
                        BTNSetEvent(PlotEvent.Plots[index].BranchPlot[i1]);
                    });
                }
            }
            else
            {
                BtnText(0).text = "继续";
                GetBTN(0).onClick.AddListener(() =>
                {
                    BTNSetEvent(PlotEvent.Plots[index].BranchPlot[0]);
                });
            }
            
        }
        
        
        
    }
/// <summary>
/// 战斗逻辑
/// </summary>
    public void EnemyATK()
    {
      
    }
    public Button GetBTN(int index)
    {
        return Buttons[index];
    }
    public Text BtnText(int index)
    {
        return Buttons[index].transform.Find("BTNtext0").GetComponent<Text>();
    }
    public void ResetBTN()
    {//这里调节文本
        if (ShowPort.text.Length>400)
        {
            ShowPort.text = ShowPort.text.Substring(ShowPort.text.Length-400, 400); 
        }
        foreach (var VARIABLE in Buttons)
        {
            VARIABLE.onClick.RemoveAllListeners();
            VARIABLE.transform.Find("BTNtext0").GetComponent<Text>().text = "";
        }
    }
}

存储

using System.Collections;
using System.Collections.Generic;
using Tutorial;
using UnityEngine;
using XLua;


    public class PlotEvent : MonoBehaviour
    {
        public class PlotClass
        {
            public int ID;
            public string Plot;
            public bool Branch;
            public bool Specail;
            public int[] BranchPlot;
        }
        [CSharpCallLua]
        public static  PlotClass[] Plots = new PlotClass[100];//被LuaModer引用

    }


LuaModer

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using XLua;

public class LuaModer : MonoBehaviour
{
    public static  LuaEnv luaEnv=new LuaEnv();
    readonly string ModPath=Application.streamingAssetsPath+"\\Mod";//Mod路径
    public PlotEvent PlotEvent;

    public void Start()
    {
        luaEnv.AddLoader(Loader);
        List<string> files = ReadFile();
        foreach (var VARIABLE in files)
        {
            string Luafile = VARIABLE.Replace(ModPath+"\\", "");//获取Mod路径中lua文本的文件名
            Luafile = Luafile.Replace(".lua.txt", "");
            luaEnv.DoString($"require '{Luafile}'");
        }

        #region 赋值
        global::PlotEvent.Plots=luaEnv.Global.Get<PlotEvent.PlotClass[]>("PlotTable");
    //    ButtonEvent.BtnEvent=luaEnv.Global.Get<ButtonEvent.LuaBtnEvent>("PlotEventBar");
        

        #endregion


    }

    /// <summary>
    /// 获取文件的方法
    /// </summary>
    List<string> ReadFile()
    {
        List<string> files = GetFiles(ModPath, "*.txt");
        foreach (var item in files)
        {
            Console.WriteLine(item);
        }
        Console.ReadKey();
        
        List<string> GetFiles(string directory, string pattern)
        {
            List<string> files = new List<string>();
            foreach (var item in Directory.GetFiles(directory, pattern))
            {
                files.Add(item);
            }
            foreach (var item in Directory.GetDirectories(directory))
            {
                files.AddRange(GetFiles(item, pattern));
            }
            return files;
        }

        return files;
    }
    

    /// <summary>
    /// 自定义加载器
    /// </summary>
    /// <param name="filepath"></param>
    /// <returns></returns>
    private byte[] Loader(ref string filePath) 
    {
        Debug.Log(filePath.ToString()); 
        string path = ModPath+"\\"+filePath+@".lua.txt";
        return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(path));
    }

}

lua部分

print "剧本加载成功"
local Unity=CS.UnityEngine.GameObject.Find("Console")
local PublicInterface=Unity:GetComponent("LuaModer")
local PlotEvent=PublicInterface.PlotEvent
local Buttons=Unity:GetComponent("ButtonEvent").Buttons
local Player=Unity:GetComponent("PlayerInfo")
-----------------------------------------------------------------
main={}
print"链接成功"
print (Player.HP)

----剧情编辑器----
PlotTable={
   
   {
		--ID:[int]剧情编号
		--Plot:[string]剧情内容 换行用 \n 表示
		--Branch:[boolean]是否分支.如果为false,可忽略.true为有
		--Specail:[boolean]是否有事件.如果为false,可忽略
		--BranchPlot:[int[]]分支或继续指向的剧情.如果是分支,要用逗号隔开
		},
	{
	ID=1,
	Plot="测试分支剧情\n 1: 恢复玩家HP10 \n 2:玩家获得一个测试的buff \n 3:玩家向北移动1格",
	Branch=true,
	BranchPlot={2,3,4}
	},
	{
		ID=2,
		Plot="剧情剧情1\n玩家的HP恢复10",
		Specail=true,
		BranchPlot={1}
		},
	{
		ID=3,
		Plot="剧情剧情2",
		Specail=true,
		BranchPlot={1}
		},
	{
		ID=4,
		Plot="剧情剧情3",
		Specail=true,
		BranchPlot={1}
	}
	}

----剧情事件编辑器----
--[[
如果剧本编辑器里的剧情启动了Specail
那么它对应的ID要在这里注册事件
预制方法:
ChangeValue(A,目标)
更改目标的数值,使目标数值与A相加

目标{
HP=生命值
EP=意志
HHP=敌人生命值
EHP=敌人意志
}
举例 ChangeValue(HP,-10) 玩家失去10HP


Effect("状态名称",可加成)
增加一个状态,双引号不能忽略.可加成部分填true或false(若false可忽略).可加成的意思是:如果已经有这个状态
就强化为+
举例 Effect("中毒",true) 玩家中毒.如果已经中毒,就改为中毒+

EffectClear("状态名称")
移除一个状态.如果状态名称是"ALL",就移除所有状态

EffectFind("状态名称")
判断是否有这个状态


Move("方向",格数)
向某方向移动几格?双引号不能忽略
方向{
Up=北
Down=南
Left=西
Right=东
}
举例 Move("UP",1) 玩家向北1格


如果以上的糖不能满足需求..属性直接调用:
Player.HP [int]玩家的体力
Player.EP [int]玩家的意志
Player.EnemyHP [int]敌人的体力(如果有)
Player.EnemyEP [int]敌人的意志(如果有)
Player.Effects [List<string>] 玩家的状态
Player.Player [GameObject] 只读:玩家单位(仅用于目标检测,判定)
]]
function PlotEventBar(ID)
	if ID<11 then
		if ID==2 then
			ChangeValue("HP",10)
		end
		if ID==3 then
			if EffectFind("一个测试状态+") then
				Effect("超强的测试状态")
			else
			Effect("一个测试状态",true)
			end
		end
		if ID==4 then
			Move("Up",1)
		end
	end
	
end
main.PlotEventBar=PlotEventBar


function ChangeValue(target,value)
	if target=="HP" then
		Player.HP=value+Player.HP
	elseif target=="EP" then
		Player.EP=value+Player.EP
	elseif target=="EHP" then
		Player.EnemyHP=value+Player.EnemyHP
	elseif target=="EEP" then
		Player.EnemyEP=value+Player.EnemyEP
	end
end

function Effect(AdV,Pls)
	if Player.Effects:Contains(AdV) or Player.Effects:Contains(AdV.."+") then
		for i = 1, Player.Effects.Count do
			if Player.Effects[i-1]==AdV then
				if Pls==true then
					Player.Effects[i-1]=AdV.."+"
				end
				break
			end
		end
	else
	Player.Effects:Add(AdV)
		end
end

function EffectFind(AdV,Plus)
	if Player.Effects:Contains(AdV) or Player.Effects:Contains(AdV.."+") then
		return true
		else return false
	end
	
end

function EffectClear(AdV)
	if Player.Effects:Contains(AdV) or Player.Effects:Contains(AdV.."+") then
		for i = 1, Player.Effects.Count do
			if Player.Effects[i-1]==AdV then
					Player.Effects:Remove(AdV)
			end
			if Player.Effects[i-1]==(AdV.."+") then
				Player.Effects:Remove(AdV.."+")
			end
		end
		end
		if AdV=="ALL" then
			Player.Effects:Clear()
		end
end


function Move(Where,Value)

	print((Player.Player:GetComponent("RectTransform").anchoredPosition3D+CS.UnityEngine.Vector3(Value*200,0,0)))
	if Where=="Left" then
		Player.Player:GetComponent("RectTransform").anchoredPosition3D=(Player.Player:GetComponent("RectTransform").anchoredPosition3D+CS.UnityEngine.Vector3(Value*200,0,0))
	end
	if Where=="Right" then
		Player.Player:GetComponent("RectTransform").anchoredPosition3D=(Player.Player:GetComponent("RectTransform").anchoredPosition3D+CS.UnityEngine.Vector3(Value*-200,0,0))
	end
	 if Where=="Up" then
		Player.Player:GetComponent("RectTransform").anchoredPosition3D=(Player.Player:GetComponent("RectTransform").anchoredPosition3D+CS.UnityEngine.Vector3(0,Value*200,0))
	end
	 if Where=="Down" then
		Player.Player:GetComponent("RectTransform").anchoredPosition3D=(Player.Player:GetComponent("RectTransform").anchoredPosition3D+CS.UnityEngine.Vector3(0,Value*-200,0))
	end
	
end
return main

效果

扫描二维码关注公众号,回复: 14649082 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_58804985/article/details/128254516
今日推荐