【问题标题】:Separating Unity C# code from "normal" C# code将 Unity C# 代码与“普通”C# 代码分离
【发布时间】:2020-01-04 14:02:33
【问题描述】:

我曾考虑将 Unity C# 代码(我只能与 UnityEngine 一起使用的代码)与“普通”C# 代码(int x = 3; bool isKnockMeDead = true; void KnockMeDead(); 等)分开

为什么?这样我就可以(例如)从 Unity 切换到 Wpf,而无需重写整个逻辑。所以我的 EngineObject 是 Window 而不是 MonoBehviour...

我已经有几个解决这个问题的方法:

但我对其中任何一个都不是 100% 满意,因为...

第一个解决方案 - InheritanceSolution.cs

这是执行此操作的最快方法,但您没有 100% 的视觉分离,并且在 Child 类中使用 Unity Code 也存在危险。

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

namespace Assets
{
    //Unity C#
    public class InheritanceSolutionParent : MonoBehaviour
    {
        public MusicPlayer EngineMusicPlayer { get; private set; }

        public void SetObjectName(string name)
        {
            gameObject.name = name;
        }

        public void MoveObjectUp(decimal y)
        {
            gameObject.transform.position += new Vector3(0, (float)y);
        }
    }

    public class MusicPlayer : MonoBehaviour, IMusicPlayer
    {
    }

    //C#
    public class InheritanceSolutionChild : InheritanceSolutionParent // => Unity
    {
        private IMusicPlayer _universalMusicPlayer;
        private List<Sound> _sounds;

        public void Start() /* => Unity */ => UniversalStart();
        public void Update() /* => Unity */ => UniversalUpdate();

        private void UniversalStart()
        {
            Initionalization();

            _sounds.Add(new Sound("Toilettenspülung", "Assets/Sounds/Toilettenspülung.mp3"));

            _universalMusicPlayer.Play(_sounds[0]);
        }

        private void Initionalization()
        {
            SetObjectName("PartialSolution");
            _universalMusicPlayer = EngineMusicPlayer; // => Unity
            _sounds = new List<Sound>();
        }

        private void UniversalUpdate()
        {
            MoveObjectUp(5);
            MoveObjectUp(2);
        }
    }

    public class Sound
    {
        public Sound(string soundName, string soundFileDataPath)
        {
            SoundName = soundName;
            SoundFileDataPath = soundFileDataPath;
        }

        public string SoundName { get; private set; }
        public string SoundFileDataPath { get; private set; }
    }

    public interface IMusicPlayer
    {
        void Play(Sound sound);
    }
}

第二个解决方案 - PartialSolution.cs

如果几个人想要在一个类上工作而不被打扰和/或如果自动生成的代码应该与用户分开,则实际使用该关键字。

我只是用它来分隔代码,还可以,但它不应该用来说每个类都有200行,因为它只是在编译时保留一个类。

还有问题:/

视觉分离将是完美的,但实现没有任何变化,我仍然可以在两个(一个)类中使用 Unity 代码。

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

namespace Assets
{
    //Unity C#
    public partial class PartialSolution : MonoBehaviour 
    {
        [SerializeField] private MusicPlayer _engineMusicPlayer;

        private void Start() => UniversalStart();
        private void Update() => UniversalUpdate();

        private void SetObjectName(string name)
        {
            gameObject.name = name;
        }

        private void SetUniversalMusicPlayer()
        {
            _universalMusicPlayer = _engineMusicPlayer;
        }

        private void MoveObjectUp(decimal y)
        {
            gameObject.transform.position += new Vector3(0, (float)y);
        }
    }

    public class MusicPlayer : MonoBehaviour, IMusicPlayer
    {
    }

    //C#
    public partial class PartialSolution
    {
        private IMusicPlayer _universalMusicPlayer;
        private List<Sound> _sounds;

        private void UniversalStart()
        {
            Initionalization();

            _sounds.Add(new Sound("Toilettenspülung", "Assets/Sounds/Toilettenspülung.mp3"));

            _universalMusicPlayer.Play(_sounds[0]);
        }

        private void Initionalization()
        {
            SetObjectName("PartialSolution");
            SetUniversalMusicPlayer();
            _sounds = new List<Sound>();
        }

        private void UniversalUpdate()
        {
            MoveObjectUp(5);
            MoveObjectUp(2);
        }
    }

    public class Sound
    {
        public Sound(string soundName, string soundFileDataPath)
        {
            SoundName = soundName;
            SoundFileDataPath = soundFileDataPath;
        }

        public string SoundName { get; private set; }
        public string SoundFileDataPath { get; private set; }
    }

    public interface IMusicPlayer
    {
        void Play(Sound sound);
    }
}

第三种解决方案 - InterfaceSolution.cs

(Ey Max 请把 GameController 类分开(大项目)...

呃...该走了

解决方案其实很完美,但付出的努力相当大!

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

namespace Assets
{
    //Unity C#
    public class InterfaceSolutionUnity : MonoBehaviour, IInterfaceSolutionUniversalEngine
    {
        IInterfaceSolutionUniversal _universalInstance;

        [SerializeField] private MusicPlayer _musicPlayer;

        public void Start()
        {
            _universalInstance = new InterfaceSolutionUniversal(this, _musicPlayer);
            _universalInstance.UniversalStart();
        }

        public void Update() => _universalInstance.UniversalUpdate();

        public void SetObjectName(string name)
        {
            gameObject.name = name;
        }

        public void MoveObjectUp(decimal y)
        {
            gameObject.transform.position += new Vector3(0, (float)y);
        }
    }

    public class MusicPlayer : MonoBehaviour, IMusicPlayer
    {
    }

    //C#
    public interface IInterfaceSolutionUniversal
    {
        void UniversalStart();
        void UniversalUpdate();
    }

    public class InterfaceSolutionUniversal : IInterfaceSolutionUniversal
    {
        private IInterfaceSolutionUniversalEngine _universalEngineInstance;

        private IMusicPlayer _musicPlayer;
        private List<Sound> _sounds;

        public InterfaceSolutionUniversal(IInterfaceSolutionUniversalEngine universalEngineInstance, IMusicPlayer musicPlayer)
        {
            _universalEngineInstance = universalEngineInstance;
            _musicPlayer = musicPlayer;
            _sounds = new List<Sound>();
        }

        public void UniversalStart()
        {
            _universalEngineInstance.SetObjectName("PartialSolution");

            _sounds.Add(new Sound("Toilettenspülung", "Assets/Sounds/Toilettenspülung.mp3"));

            _musicPlayer.Play(_sounds[0]);
        }

        public void UniversalUpdate()
        {
            _universalEngineInstance.MoveObjectUp(5);
            _universalEngineInstance.MoveObjectUp(2);
        }
    }

    public interface IInterfaceSolutionUniversalEngine
    {
        void MoveObjectUp(decimal y);
        void SetObjectName(string name);
    }

    public class Sound
    {
        public Sound(string soundName, string soundFileDataPath)
        {
            SoundName = soundName;
            SoundFileDataPath = soundFileDataPath;
        }

        public string SoundName { get; private set; }
        public string SoundFileDataPath { get; private set; }
    }

    public interface IMusicPlayer
    {
        void Play(Sound sound);
    }
}

我的问题:

  1. 还有必要吗?如果是,什么时候?

  2. 您认为这三个中哪一个是最好的?

  3. 还有更好的吗?

总而言之,我只是想从 Unity 中独立一点,但我不想马上编写新引擎。

你可以留给我最终如何设计它。 (MVVM、MVC 等):)

期待您的回答。 请成为我的英雄!

【问题讨论】:

  • 接口解决方案是我会使用的解决方案。接口正是为此目的而设计的。
  • 我同意这一点。
  • 一个统一的c#逻辑可以在不同的框架中使用?您最好将它们尽可能分开,因为您的解决方案仍然相互关联。打个比方,想想你的逻辑加油站和另一端(统一,wpf 等......)就像一辆汽车。您正在尝试(或者我认为您正在尝试)将 fuel 连接到 car-engine。你的逻辑和它的用户应该有和点(非常狭窄,abstarct ones | 油箱)与他们建立联系。用 C# 独立编写整个逻辑,同时考虑这些端点..​​....或者我只是没有理解你:)

标签: c# .net unity3d design-patterns code-separation


【解决方案1】:

我从事过这样的项目。这很棒,但也让不断地与 Unity 战斗很头疼。我们的原因是要有一个确定性游戏,并将其实例作为权威服务器运行,而不涉及 Unity。

MVC 非常适合这个。

我刚才创建了minimal project。看看吧。

  • 模型仅包含数据。
  • View 是一个带有 SpriteRenderers/AudioSources 的 MonoBehaviour,用于监听事件。
  • 事件是视图感兴趣的模型更改。
  • 服务是修改模型的方法的集合。
  • 模拟器为模型打勾。
  • 上下文是一切的开始。

【讨论】:

  • 答案很有帮助,但很遗憾没有回答我的问题!如果有比我的更好的,我想要两个类(一个 Unity,一个 Universal)的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多