基于组件的设计(C# 游戏引擎)

Posted

技术标签:

【中文标题】基于组件的设计(C# 游戏引擎)【英文标题】:Component Based Design (C# Game Engine) 【发布时间】:2017-07-27 00:55:07 【问题描述】:

我目前正在使用 GDI+ 在 c# 中设计一个 2D 游戏引擎,但我的代码中遇到了一个可怕的设计缺陷。

这个想法是我的游戏引擎由多个屏幕组成,每个屏幕包含多个游戏对象,每个游戏对象包含多个组件(就像 unity 一样)。与前一个游戏对象相比,每个游戏对象都可以包含不同的组件。

例如,假设我有一个会弹跳的球。我需要一个物理组件和一个变换组件。

但是,我意识到某些组件依赖于其他组件才能工作。

在我上面提到的物理组件的情况下,需要访问变换组件来更新和知道球的位置、旋转等。

所以目前,我的基础组件类也包含对它当前附加的 GameObject 的引用,因此任何组件都可以访问游戏对象中的任何其他组件。

我只是想知道这是否是实现基于组件的引擎的最佳方法。

下面是 Sprite 组件的脚本,需要访问游戏对象的位置。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GameEngine.Components

    /// <summary>
    /// 
    /// </summary>
    /// <seealso cref="GameEngine.Components.Component" />
    /// <seealso cref="System.IDisposable" />
    public class Sprite : Component, IDisposable
    
        /// <summary>
        /// The bitmap the graphics engine renders
        /// </summary>
        private Bitmap bitmap;

        /// <summary>
        /// Initializes a new instance of the <see cref="Sprite"/> class.
        /// </summary>
        /// <param name="bitmap">The bitmap.</param>
        public Sprite(Bitmap bitmap)
        
            this.bitmap = bitmap;

            this.Events.OnRenderFrame += Events_OnRenderFrame;
        

        /// <summary>
        /// Handles the OnRenderFrame event of the Events control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RenderEventArgs"/> instance containing the event data.</param>
        private void Events_OnRenderFrame(object sender, RenderEventArgs e)
        
            // Uses the game objects transform component, to get the position of the object
            e.GraphicsEngine.DrawSprite(this, GameObject.GetComponentOfType<Transform>().Position);
        

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        
            bitmap.Dispose();
        
    

【问题讨论】:

unity 假设每个游戏对象都具有所有组件(或在早期版本中假设),这就是您看到 gameobject.transform 或 gameobject.rigidbody2D 可访问的原因 【参考方案1】:

但是,我意识到某些组件依赖于其他组件 上班。

在我上面提到的物理组件的情况下,需要访问 用于更新和了解球位置的变换组件, 旋转等。

是的,这是真的,但这不是问题。这是一项无法消除的要求,因为有时两个或多个组件一起工作以实现目标。但是您可以通过在代码中添加依赖组件来使其更明智,因为 Require Component attribute 通常在 Unity 中使用。

您应该记住,除了这种基于组件的模型的几个优点之外,完全独立是无法实现的。

组件应该适合部署到任何合适的 环境,因此它们应该拥有与 其他组件[它们应该是,但不可能在每种情况下都可能,例如您的情况或统一游戏引擎]。这确保了特定的部署 组件不会以任何方式影响整个系统。(more)

注意:您有权不同意答案或提供更温和的答案以确保decoupling

【讨论】:

以上是关于基于组件的设计(C# 游戏引擎)的主要内容,如果未能解决你的问题,请参考以下文章

Unity游戏引擎都有哪些优势

什么是游戏引擎?

基于UNITY引擎开发的游戏源码修改方法

开源游戏引擎哪家强?八款知名引擎资料够你忙

《游戏引擎架构》笔记十四

Storm-Engine 基于 C++ 的开源游戏引擎