unity剧情系统开发

从去年三月份到现在,《匣》断断续续的也经历一年多的开发,这几天剧情系统也算是稳定下来了,后面应该不会再进行大概了,一开始还搞了个节点编辑器,结果后来整个剧情跳转逻辑改了,编辑器也没用了。后面有时间还是想把编辑器搞起来,否则配表真的是太麻烦了。

简介

  《匣》是一款剧情向的2d游戏,所有整个剧情系统是基于文字内容的,并不需要什么人物的行为。基于这一点,整个剧情系统主体分为下面三部分

  • StoryManager
  • StoryData/StoryHandler
  • TriggerData/TriggerHandler

StoryManager

  这个管理器并不直接管理剧情,它既不存储剧情数据,也不定义某个剧情的表现形式。当你传了一个剧情数据或者是触发器数据给它时,它会根据数据类型选择对应的Handler再具体去做某件事。系统的核心部分是没有对数据进行管理的,所以数据怎么存储可以由外界定义。

StoryHandler

  按照我们的设计需要,剧情被分为了普通,CG,顾客等几种,每种剧情都有着自己的表现方式。所有就有个了StoryHandler(剧情处理器)的概念。每种类型的剧情都对应一个处理器。处理器核心代码只有一个接口和一个泛型基类。泛型基类的方法只有OnHandleStory是其派生类必须实现的,并且要定义好剧情处理完成的时机去调用callback。其他方法一般不用重写。

public interface IStoryHandler
{
    /// <summary>
    /// 对应的故事类型
    /// </summary>
    Type StoryDataType { get; }
    /// <summary>
    /// 处理剧情数据
    /// </summary>
    /// <param name="storyDataBase">剧情</param>
    /// <param name="callback">完成后的回调</param>
    void Handle(StoryDataBase storyDataBase, Action callback = null);
}

public abstract class StoryHandlerBase<T> : IStoryHandler where T : StoryDataBase
{
    public Type StoryDataType => typeof(T);
	/// <summary>
	/// 处理剧情数据
	/// </summary>
	/// <param name="storyDataBase">剧情</param>
	/// <param name="callback">完成后的回调</param>
    public void Handle(StoryDataBase storyDataBase, Action callback = null)

    /// <summary>
    /// 开始故事前检查是否满足触发条件
    /// </summary>
    /// <param name="storyData"></param>
    /// <returns></returns>
    protected virtual bool OnCheckStory(T storyData)

    /// <summary>
    /// 处理故事
    /// </summary>
    /// <param name="storyData"></param>
    /// <param name="callback">故事结束后的回调</param>
    protected abstract void OnHandleStory(T storyData, Action callback);

    /// <summary>
    /// 故事结束后处理一些事情,比如后续剧情
    /// </summary>
    /// <param name="storyData"></param>
    protected virtual void OnStoryEnd(T storyData)
}

TriggerHandler

  一个剧情结束后,可能会触发其他剧情,但触发方式不一样,有的可能会立即触发,有的可能会隔几天,等等。这样一来,就需要多种触发器来定义一个剧情被触发的方式。
  触发器的核心代码和剧情处理器基本一致,并且更简单一些,也是一个接口和一个泛型基类。
  在匣开发过程中,并不是每一种触发器数据都对应一个处理器。有些触发器可能会在别的地方处理。这一点是同剧情处理器不一样(如果某种类型的剧情没有定义对应的处理器,该数据在传给StoryManager后会抛出一个异常)

/// <summary>
/// 故事触发处理器
/// </summary>
public interface ITriggerHandler
{
    Type TriggerDataType { get; }
    void Handle(ITriggerData triggerData);
}

/// <summary>
/// 故事触发数据的处理器基类
/// </summary>
/// <typeparam name="T">触发器类型</typeparam>
public abstract class StoryTriggerHandlerBase<T> : ITriggerHandler where T : ITriggerData
{
    public Type TriggerDataType => typeof(T);
    public void Handle(ITriggerData triggerData)
    protected abstract void HandleTriggerData(T triggerData);
}

总结

  有了这些基础代码之后,再对应去实现所需要的剧情表现形式,可以实现一个相对比较丰富的文字剧情系统。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的Unity答题系统开发的步骤: 1.创建题目和答案的数据结构,可以使用XML文件或者其他数据存储方式。 2.创建一个答题界面,包括题目、选项、倒计时等元素。 3.创建一个计时器,用于倒计时并在时间结束后关闭答题界面。 4.创建一个按钮组件,用于选择题目。 5.创建一个按钮点击事件,用于检查答案是否正确并更新得分。 6.创建一个结束界面,显示得分和其他统计信息。 7.将所有组件和事件连接起来,以实现完整的答题系统。 以下是一个简单的Unity答题系统的代码示例: ```csharp using System.Collections;using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Question { public string question; public List<string> options; public int answer; } public class QuizManager : MonoBehaviour { public Text questionText; public List<Button> optionButtons; public Text scoreText; public Text timeText; public GameObject quizPanel; public GameObject resultPanel; private List<Question> questions; private int currentQuestionIndex; private int score; private float timeLeft; private bool answered; void Start() { LoadQuestions(); StartQuiz(); } void Update() { if (timeLeft > 0) { timeLeft -= Time.deltaTime; timeText.text = Mathf.RoundToInt(timeLeft).ToString(); } else if (!answered) { EndQuiz(); } } void LoadQuestions() { // Load questions from XML file or other data source // ... } void StartQuiz() { currentQuestionIndex = 0; score = 0; timeLeft = 60; answered = false; quizPanel.SetActive(true); resultPanel.SetActive(false); ShowQuestion(); } void EndQuiz() { quizPanel.SetActive(false); resultPanel.SetActive(true); scoreText.text = "Score: " + score.ToString(); } void ShowQuestion() { Question question = questions[currentQuestionIndex]; questionText.text = question.question; for (int i = 0; i < optionButtons.Count; i++) { optionButtons[i].GetComponentInChildren<Text>().text = question.options[i]; } } public void AnswerQuestion(int answer) { if (!answered) { Question question = questions[currentQuestionIndex]; if (answer == question.answer) { score++; } currentQuestionIndex++; if (currentQuestionIndex < questions.Count) { ShowQuestion(); } else { answered = true; EndQuiz(); } } } public void SelectQuestion(int index) { if (!answered) { currentQuestionIndex = index; ShowQuestion(); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值