Unity题目开发简易框架

正常开发流程中,通常会遇到很多的题目开发,常见的有选择题、填空题、问答题等。当然这些功能的开发很简单,但是,如果没有一套通用的框架来进行管理,而是每一个或每一种题目都写上一套代码,那么后期的迭代和维护都会收到很多的影响,为了解决这个问题,闲暇之余,做了一个简单的题目框架,能够支持和拓展以上说到的所有题型。

首先我定义了一个接口IQuestion,后期所有的题目都继承自这个接口,接口内容如下

public interface IQuestion
{
    /// <summary>
    /// quesItem列表
    /// </summary>
    List<IQuesItem> questionItemList { get; set; }
    /// <summary>
    /// quesItem的数量
    /// </summary>
    int quesItemCount { get; }
    /// <summary>
    /// 增加一个QuesItem
    /// </summary>
    /// <param name="item"></param>
    void AddQuesItem(IQuesItem item);
    /// <summary>
    /// 移除一个QuesItem
    /// </summary>
    /// <param name="item"></param>
    void RemoveQuesItem(IQuesItem item);
    /// <summary>
    /// 清空所有QuesItem
    /// </summary>
    /// <param name="item"></param>
    void ClearQuesItem();
    /// <summary>
    /// 提交
    /// </summary>
    /// <returns></returns>
    bool Submit();
    /// <summary>
    /// 是否回答正确
    /// </summary>
    /// <returns></returns>
    bool IsRight();
    /// <summary>
    /// 根据索引获取QuesItem
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    IQuesItem GetQuesItem(int id);
}

那么在上面的IQuestion接口中引入了一个新接口IQuesItem。
什么是IQuesItem?
其实简而言之就是,拿选择题举例子,每一个选项A/B/C/D都是一个QuesItem,如果是填空题,那么每一个需要输入的空格就是一个QuesItem。
为什么引入IQuesItem这个接口?
因为考虑到后期每一个操作单元的展示、效果、操作方式都有可能不同,那么这个时候,所有的这些可能情况,非常适合做一个多态处理,那么后期每一个操作单元都是一个独立的个体,提高操作单元的灵活性

/// <summary>
/// 操作单元
/// </summary>
public interface IQuesItem
{
    /// <summary>
    /// 目标结果
    /// </summary>
    object targetAnswer { get;}
    /// <summary>
    /// 实际当前结果
    /// </summary>
    object curAnswer { get; }
    /// <summary>
    /// 实际当前结果改变
    /// </summary>
    /// <param name="value">改变之后</param>
    void OnChanged(object value);
    /// <summary>
    /// 是否回答正确
    /// </summary>
    /// <returns></returns>
    bool IsRight();
    /// <summary>
    /// 回答正确之后的反应
    /// </summary>
    void OnRight();
    /// <summary>
    /// 回答错误之后的反应
    /// </summary>
    void OnError();
}

其实写到这里基础结构就已经确定了,后期题目对象继承IQuestion,所有的操作单元继承IQuesItem,然后分别在具体对象中进行多态。
但是到这时我们发现,由于接口无法实现具体的方法,为了提高开发速度,我在实际对象和题目接口之间又做了一次封装。

public abstract class Question : MonoBehaviour,IQuestion
{
    private IQuestion iquestion=>this;
    List<IQuesItem> IQuestion.questionItemList { get; set; }
    public int quesItemCount => iquestion?.questionItemList == null ? 0 : iquestion.questionItemList.Count;

    protected virtual void Awake()
    {
        IQuesItem[] items = transform.GetComponentsInChildren<IQuesItem>();
        if (items!=null&&items.Length>0)
            for (int i = 0; i < items.Length; i++)AddQuesItem(items[i]);
    }

    public IQuesItem GetQuesItem(int id)
    {
        if (id>=quesItemCount) return null;
        return iquestion.questionItemList[id];
    }

    /// <summary>
    /// 提交答案
    /// </summary>
    /// <returns>返回正误</returns>
    public virtual void OnSubmit()
    {
        bool isRight = iquestion.Submit();
        SubmitResult(isRight);
    }

    protected abstract void SubmitResult(bool isRight);

    /// <summary>
    /// 添加一个QuesItem
    /// </summary>
    /// <param name="item"></param>
    public void AddQuesItem(IQuesItem item)
    {
        if (iquestion.questionItemList==null)iquestion.questionItemList=new List<IQuesItem>();
        iquestion.questionItemList.Add(item);
    }

    /// <summary>
    /// 移除一个QuesItem
    /// </summary>
    /// <param name="item"></param>
    public void RemoveQuesItem(IQuesItem item)
    {
        if (quesItemCount==0) return;
        iquestion.questionItemList.Remove(item);
    }

    /// <summary>
    /// 清空所有QuesItem
    /// </summary>
    public void ClearQuesItem()
    {
        if (iquestion.questionItemList!=null)iquestion.questionItemList.Clear();
    }

    /// <summary>
    /// 当前回答是否正确
    /// </summary>
    /// <returns>返回正误</returns>
    public bool IsRight()
    {
        if (quesItemCount==0) return false;
        bool isRight = true;
        for (int i = 0; i < quesItemCount; i++)
        {
            if (!GetQuesItem(i).IsRight())
            {
                isRight = false;
                break;
            }
        }
        return isRight;
    }

    #region 私有
    bool IQuestion.Submit()
    {
        if (quesItemCount == 0) return false;
        IQuesItem curItem = null;
        bool isRight = true;
        for (int i = 0; i < quesItemCount; i++)
        {
            curItem = GetQuesItem(i);
            if (curItem.IsRight())curItem.OnRight();
            else
            {
                isRight = false;
                curItem.OnError();
            }
        }
        return isRight;
    }

    #endregion
    
}

那么可以看到,Question对象继承自MonoBehaviour,和IQuestion接口,首先继承自MonoBehaviour是为了简化初始数据的配置,继承IQuestion接口则是为了实现题目的基础功能,并且,Question是一个抽象对象,目的是为了防止程序开发中直接使用Question并修改内部数据和逻辑,保证这个对象的统一性。
所以,之后所有的题目对象我们都可以继承自Question而不是IQuestion接口

写到其实就已经完事了,但是不让看看效果总感觉少点什么。
莫方! 下面就做一个简单的小测试,就拿选择题开刀吧。
那么我把选择题对象命名为ChooseQues,当然要继承Question了

/// <summary>
/// 选择题
/// </summary>
public class ChooseQues : Question
{
    [SerializeField]
    private Text tipText;
    [SerializeField]
    private Button submitBtn;

    private void Start()
    {
        submitBtn.onClick.AddListener(OnSubmit);
    }

    protected override void SubmitResult(bool isRight)
    {
        tipText.text = isRight ? "回答正确" : "回答错误";
    }

}

怎么样?选择题对象只需要写这么一丢丢代码就能够实现,提交和提示功能了。。。。。
是不是还少点啥?
没错了,还少每个操作单元(选项)对象了,那么我把每个操作单元叫做ToggleItem,因为每个选项我都是用Toggle做的,当然你也可以用其他方式。

public class ToggleItem : MonoBehaviour,IQuesItem
{
    [SerializeField]
    private bool answer;
    public object targetAnswer => answer;
    public object curAnswer => toggle.isOn;
    private Toggle toggle;
    private Text effectText;

    private void Start()
    {
        toggle = GetComponent<Toggle>();
        toggle.onValueChanged.AddListener(isSelect=>OnChanged(isSelect));
        effectText = transform.Find("EffectText")?.GetComponent<Text>();
    }

    public void OnChanged(object value)
    {
        Debug.Log(transform.name+": 变为:"+(bool)value);
    }

    public bool IsRight()
    {
        return (bool) curAnswer == (bool) targetAnswer;
    }

    public void OnRight()
    {
        if (effectText)effectText.text = "选择正确";
    }

    public void OnError()
    {
        if (effectText)effectText.text = "选择错误";
    }
}

这次真的写完了哈。。
可以看到这个对象有一个字段targetAnswer 对了 这个就是目标答案(可以再面板进行配置),接口中是object类型的,因为后期他的数据类型可能不固定,例如这里使用bool值作为目标答案即可。
还有一个字段叫curAnswer,这个字段是当前实际录入的答案,那么显然只需要我们在IsRight()中判断他们两个是否结果协同就Ok了。
effectText 是做了一个简单的效果(文字提示,这个操作块,是否正确?)当然,你也可以在里面做非常酷炫的效果,直接写在OnRight()【回答正确之后的效果】和OnError()【回答错误之后的效果】中就好了。
效果图如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
最后附上源码链接,源码中还实现了填空题和九宫格拼图的题目类型。
源码

  • 26
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: Unity是一款广泛使用的游戏开发引擎。它提供了可视化的编辑器界面、底层的渲染引擎以及广泛支持的插件生态系统,使得开发者可以很方便地进行游戏开发。 如果你准备参加Unity的面试笔试,你需要掌握以下方面的知识: 1. 编程语言:Unity支持C#和JavaScript语言。你需要掌握其中一种或两种编程语言,并且能够熟练应用它们。 2. 游戏设计:你需要具备游戏设计的基本知识,包括游戏流程、关卡设计、角色设计、游戏平衡等方面的知识。 3. Unity编辑器:你需要熟练掌握Unity编辑器的各种工具,例如场景编辑、组件列表、资源管理等。 4. 物理引擎:Unity包含了物理引擎,你需要熟悉它的基本概念,例如重力、力、碰撞等。 5. 动画系统:游戏中的角色动画是非常重要的一部分,你需要熟悉Unity的动画系统,包括动画控制器、状态机等。 总之,如果你想要在Unity领域取得成功,你需要在以上方面进行深入学习和掌握。如果你能够在面试笔试中展现出你的知识和技能,相信你会很快获得工作机会。 ### 回答2: Unity是当前市面上非常流行的游戏引擎,而从事Unity开发的人才需求也越来越大。在面试和笔试中,可能会涉及到Unity的相关知识和技能。下面将从Unity的四个方面进行简单介绍:游戏物体、组件、Scene和Asset以及C#语言。 1. 游戏物体 在Unity中,物体(GameObject)是游戏场景中的核心对象。而每一个场景都是由若干个物体组成,物体又是由若干个组件(Component)组成的。因此,需要了解游戏物体的各种操作和属性设置,包括名称、激活状态、位置、旋转、缩放、父子关系等。 2. 组件 组件是Unity中最常用的一种对象,也是游戏物体的一个基本组成部分。它可以改变游戏物体的行为、外观和互动方式。在Unity中,可以通过添加或删除组件来更改游戏物体的属性和行为。例如,常用的组件包括:Animator、Rigidbody、Collider等。 3. Scene和Asset Scene(场景)是Unity的一个概念,是由多个游戏物体和它们的组件组成的。在进行游戏开发时,需要了解如何创建、导入和导出Scene。而Asset(资源)则是指Unity中的各种资源文件,例如:纹理、音频、3D模型、动画等。需要了解如何使用Asset Store、如何导入和设置Asset等。 4. C#语言 Unity使用C#语言作为主要的编程语言。因此,在进行Unity开发时,需要了解一些基本的C#语言语法和编程思想,包括:变量、方法、类、继承、多态、接口、委托等。此外,还需要了解一些Unity特有的API和对象模型,例如:GameObject、Component、Transform、Input、Physics等。 总体来说,对于Unity的面试和笔试,需要具备扎实的Unity框架和常用组件的运用能力,同时还能够掌握C#语言的基本知识。只有掌握了这些核心技能,才能在Unity开发中不断提升自己,并为团队和项目创造出更多价值。 ### 回答3: Unity 是一款非常流行的游戏开发引擎,其在市场上占有非常重要的地位,因此很多人选择学习和使用 Unity。如何通过 Unity 的面试笔试题来测试候选人的实际技能以及对 Unity 开发的理解和掌握程度呢? 对于 Unity 的面试笔试题,一般会涉及以下几个方面: 1. 编程语言和算法基础 Unity 开发主要使用 C# 语言,因此需要候选人具备扎实的 C# 基础和算法基础,包括数据结构、算法思想、设计模式等方面的知识。 2. Unity 引擎和 API 掌握程度 作为 Unity 开发者,需要掌握很多 Unity 引擎和 API 的知识,比如场景管理、游戏物体与组件、UI 界面开发、动画系统、物理引擎等。针对这些方面,笔试题目可能会让候选人通过代码实现相关功能或者回答相关问题。 3. 项目经验和实践能力 除了理论知识,实际项目经验和实践能力也非常重要。因此,笔试题目可能会涉及到一些实际场景的开发问题,比如优化性能、解决 bug、协作开发等方面。 总之,Unity 面试笔试题主要考察候选人的编程能力、Unity 引擎和 API 掌握程度以及项目实践能力。同时,需要候选人具备良好的沟通能力和团队合作精神,这对于实际开发非常重要。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

司军礼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值