unity3d 收费模式_unity3d中的访客模式

article/2025/10/22 23:19:03

unity3d 收费模式

抽象 (Abstract)

Game development as a discipline is challenging on its own compared to traditional software development. The ability to solve performance-related, architectural and other challenges is often the key to success in the field. Because of these and many other factors, it is often a good practice to follow certain software principles and common practices to enforce the maintainability and extensibility of a product. Software design patterns come in handy in such scenarios. They can make the code base more maintainable, extensible, and contribute significantly to the overall lifetime of a product. One of the use cases to be examined is the application of the visitor pattern (Gamma, et al. 1995) in the context of game development. Possible challenges and benefits of the pattern implementation are outlined respectively in this writing.

与传统软件开发相比,将游戏开发作为一门学科本身具有挑战性。 解决与性能相关,体系结构和其他挑战的能力通常是该领域成功的关键。 由于这些因素和许多其他因素,遵循某些软件原理和通用惯例来强制执行产品的可维护性和可扩展性通常是一个好习惯。 在这种情况下,软件设计模式会派上用场。 它们可以使代码库更具可维护性,可扩展性,并为产品的整个生命周期做出重大贡献。 要研究的用例之一是访客模式在游戏开发中的应用(Gamma等,1995)。 本文分别概述了模式实现的可能挑战和好处。

前言 (Preface)

The scenario used is completely fictional and resembles an isolated use case. The degree of design completeness in the classes is not meant to be a subject for evaluation of any kind and is simplified to emphasize the point of the paper and not to clutter the code with proper, secure programming construction. Edge case checks are omitted along with many other optimization-related techniques to illustrate the point of the topic.

使用的场景完全是虚构的,类似于孤立的用例。 这些类中的设计完整性程度并不意味着要进行任何形式的评估,而应简化以强调本文的要点,并且不要以正确,安全的编程结构使代码混乱。 省略了边缘案例检查以及许多其他与优化相关的技术,以说明该主题的重点。

This writing is a purely personal interpretation and vision of the matter based on the challenges I have encountered while coding and trying to accept Unity3d component-based architecture.

基于我在编码和尝试接受基于Unity3d组件的体系结构时遇到的挑战,本文只是对此问题的纯个人解释和构想。

Full source code can be found in my GitHub repo: https://github.com/george-vasilchenko/unity-visitor

完整的源代码可以在我的GitHub存储库中找到: https : //github.com/george-vasilchenko/unity-visitor

问题 (The Problem)

To examine the usefulness and applicability of the visitor pattern within game logic, we sketch the following scenario. Consider the following diagram, to begin with:

为了检查游戏逻辑中访客模式的有用性和适用性,我们绘制了以下场景。 首先考虑下图:

Image for post

The setup is quite straightforward. We have an abstract base class with a few common members for a character. See the code for the CharacterBase class:

设置非常简单。 我们有一个抽象基类,该基类有几个常见的角色成员。 请参见CharacterBase类的代码:

Each of the child classes implements the required members accordingly. The characters have a default set of stats assigned during the initialization. The starting level for each character is 1. To perform an attack, according to my fictional scenario, it is important to calculate damage for the attack. There are hundreds of ways this can be implemented of course but, in my case, it will be a calculation based on the weighted distribution of the stats of a particular character. Here is the implementation of the Attack and CalculateDamage methods from the Archer class:

每个子类都相应地实现所需的成员。 这些字符在初始化期间分配了一组默认的统计信息。 每个角色的起始级别为1。根据我的虚拟场景,要进行攻击,计算攻击的伤害很重要。 当然,有数百种方法可以实现,但就我而言,这将基于特定角色的统计信息的加权分布进行计算。 这是Archer类中AttackCalculateDamage方法的实现:

The idea is that each character, based on its type (Archer, Paladin, etc) has its leading trait. Archer, for instance, has agility as his main trait. In contrast, a magician uses intelligence as the main characteristics. This trend is implemented in the CalculateDamage methods for each of the characters.

这个想法是,每个角色根据其类型(Archer,Paladin等)都有其主导特征。 例如,弓箭手以敏捷为主要特征。 相反,魔术师则以智力为主要特征。 此趋势在CalculateDamage方法中为每个字符实现。

The problem here, however, is that we keep this distribution information in each character class. At the first sight, this seems reasonable, but if we will implement a more advanced way of resolving these numbers, we will need to introduce dependencies in each character class and the code will become less flexible.

但是,这里的问题是,我们在每个字符类中保留了此分发信息。 乍一看,这似乎是合理的,但是如果我们将采用更高级的方式来解析这些数字,则需要在每个字符类中引入依赖关系,并且代码的灵活性将降低。

Let’s consider another scenario for the characters. The ability to level-up in the game can be a desired feature. Usually, this kind of functionality is essential. The ability to increase the level, in my scenario, impacts the damage amount that a character can produce. With each level, normally, a character would deal more and more damage, this is also the case in my fictional scenario. Consider the following implementation of the IncreaseLevel method:

让我们考虑字符的另一种情况。 在游戏中升级的能力可能是理想的功能。 通常,这种功能是必不可少的。 在我的情况下,提高等级的能力会影响角色可能产生的伤害量。 通常,在每个级别上,角色都会造成越来越多的伤害,在我的虚拟场景中也是如此。 考虑下面的GrowthLevel方法的实现:

We increment the level member variable each time the method is called. For us to come up with a proper stat increase for a given level, we should increment each stats property each time the level is increased. Using the CreateFromOtherWithDeltas method of structure CharacterStats, gives us the updated stats instance that is built on top of the existing one and with the delta for each property. The implementation of the CharacterStats structure:

每次调用该方法时,我们都会增加级别成员变量。 为了让我们针对给定的级别提出适当的统计信息增加,每次级别增加时,我们都应该增加每个统计信息属性。 使用CharacterStats结构的CreateFromOtherWithDeltas方法,可以为我们提供更新的stats实例,该实例建立在现有实例的基础上,并具有每个属性的增量。 CharacterStats结构的实现:

To sum it up, we calculate stats deltas based on the level of the character and we update the stats reference with a new object. This, in turn, will be used in the CalculateDamage method to come up with the final damage amount.

综上所述,我们根据字符的级别计算统计数据增量,并使用新对象更新统计数据引用。 反过来,它将在CalculateDamage方法中使用,以得出最终的损坏量。

The direction where this implementation is heading is obvious. We keep extending the class with the implementation of every new level, besides, in a more advanced scenario, the resolution of the stats values would be delegated to an external class which in turn would become a dependency for the character class. And this repeats for each new character we desire to add in the game. This will bring maintenance problems, high complexity of the character classes, and tight coupling between possible external modules that provide numeric data for this logic.

该实现的方向很明显。 我们将通过每个新级别的实现来扩展类,此外,在更高级的情况下,统计值的解析将委派给外部类,而外部类又将成为字符类的依赖项。 对于我们希望添加到游戏中的每个新角色,此操作都会重复。 这将带来维护问题,字符类的高度复杂性以及可能为此逻辑提供数字数据的外部模块之间的紧密耦合。

有希望的解决方案 (The Promising Solution)

The Visitor pattern, according to Gamma, et al. (1995), is intended to

访客模式,根据Gamma等人的说法。 (1995),旨在

“represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.”

“表示要在对象结构的元素上执行的操作。 访问者可让您定义新操作,而无需更改其所操作元素的类。”

This definition strikes as a possible solution to achieve the needed maintainability in the classes from the fictional scenario. Let’s try to implement such a pattern and analyze whether it will enhance the quality and design of the program.

该定义是从虚拟场景中实现类中所需的可维护性的可能解决方案。 让我们尝试实现这种模式,并分析它是否会提高程序的质量和设计。

I have gone ahead and refactored the code to fit the pattern. A few more classes have emerged. Consider the new diagram:

我已经继续并重构了代码以适应模式。 出现了更多的类。 考虑新图:

Image for post

Types like IDamageable and Enemy are just supplementary components to make the scenario more or less complete, they are used in the Attack method of each character. I have introduced a few more types, specifically ICharacterVisitor<T> and two implementations of this interface: StatsDistributionVisitor and StatsIncreasePerLevelVisitor. The first one was designed to take responsibility for the distribution logic that is used by each character in a specific way, and the latter is meant to tackle the level-based stats problem. I moved all related code from the character classes into the visitor classes respectively. StatsDistribution structure was introduced to encapsulate the concept of stats deltas. The code for the distribution visitor:

诸如IDamageableEnemy之类的类型只是使场景或多或少完整的补充组件,它们在每个角色的Attack方法中使用。 我介绍了更多类型,特别是ICharacterVisitor <T>和此接口的两个实现: StatsDistributionVisitorStatsIncreasePerLevelVisitor 。 第一个设计用于负责每个角色以特定方式使用的分配逻辑,而后者则旨在解决基于级别的统计问题。 我将所有相关代码分别从字符类移到了访客类。 引入了StatsDistribution结构来封装stats deltas概念。 分发访问者的代码:

Here we can see that values that were provided in the CalculateDamage method are moved into this class and it is way easier to maintain this structure. The stats distribution logic is now in one place and can be easily extended by any external source. For instance, we can use a ScriptableObject (Unity, 2018) instance to manipulate these values from the Editor, which would be a good solution for level designers and testers.

在这里,我们可以看到CalculateDamage方法中提供的值已移入此类,并且可以更轻松地维护此结构。 统计信息分配逻辑现在处于一个位置,可以通过任何外部源轻松扩展。 例如,我们可以使用ScriptableObject (Unity,2018)实例从编辑器中操纵这些值,这对于关卡设计人员和测试人员而言将是一个很好的解决方案。

The second visitor class is responsible for determining a boost for the stats for each character based on the level. Here is the implementation in code:

第二个访问者类负责根据级别确定每个角色的属性提升。 这是代码中的实现:

The level stats logic was moved from the character classes into the visitor class. Similarly, this class can also take advantage of additional dependencies. This approach takes the burden concerning level-based upgrades away from the character classes.

级别统计逻辑已从角色类移至访客类。 同样,此类也可以利用其他依赖项。 这种方法减轻了基于角色升级的负担。

Let’s take a look at the actual use of the visitor classes by, say, the Mage class:

让我们看一下Mage类对访客类的实际使用:

The size of the class is reduced. The amount of level related logic will no longer affect this class because the logic is placed in the visitor class. The distribution logic is also substituted with the call to the Visit method of the distribution visitor.

班级人数减少。 与级别相关的逻辑的数量将不再影响此类,因为该逻辑已放置在visiter类中。 分发逻辑也用对分发访问者的Visit方法的调用代替。

测试中 (Testing)

To try out both implementations, I have set up a few simple editor-based unit tests. The tests take care of creating instances of the characters. Each character gets its enemy to attack. To not overengineer the scenario and to not sway from the topic, the assessment logic simply examines the change in the health of each enemy. Additionally, the information is logged into the console to illustrate the difference. The tests are identical concerning the implementation before the visitor pattern and after, the only difference is the character class implementations. Here is the sample code for one of the tests:

为了尝试这两种实现,我建立了一些简单的基于编辑器的单元测试。 测试负责创建字符实例。 每个角色都会受到敌人的攻击。 为了不对场景进行过度设计并且不偏离主题,评估逻辑仅检查每个敌人的健康状况变化。 此外,该信息将记录到控制台中以说明差异。 关于访问者模式之前和之后的实现,测试是相同的,唯一的区别是字符类实现。 以下是其中一项测试的示例代码:

The results of the tests are identical. Here is the result for the implementation without the visitor pattern:

测试结果是相同的。 这是没有访问者模式的实现结果:

Image for post

Here is the result after the visitor pattern was implemented:

这是实现访客模式后的结果:

Image for post

思想 (Thoughts)

Considering the amount of effort it takes to implement game logic in game development, it is essential to find an efficient way to do that. Using software design patterns is considered good practice but the patterns have to be applied with a reason and caution. It is often tempting to over-complicate design and implementation, which, in result, puts the success of a product at risk. Unity3d coding approach follows a component-based design (Component-based software engineering, 2020). It is quite challenging to follow object-oriented principles in such an environment when architecture works against you. However, in certain isolated components, it is possible to tackle problems by following common best practices. The visitor pattern appears to be useful in scenarios when we have to deal with multiple objects of the same structure that have to implement certain operations. Visitor lets us keep related operations together by defining them in one class (Gamma, et al. 1995). This opens additional opportunities to make use of the reach feature set of the engine when we want to influence the data of the visitor classes.

考虑到在游戏开发中实现游戏逻辑所需的工作量,找到一种有效的方法至关重要。 使用软件设计模式被认为是一种很好的做法,但是必须谨慎使用这些模式。 通常,设计和实现过于复杂是很诱人的,这最终使产品的成功受到威胁。 Unity3d编码方法遵循基于组件的设计(基于组件的软件工程,2020)。 当架构不利于您时,在这样的环境中遵循面向对象的原则是非常具有挑战性的。 但是,在某些隔离的组件中,可以通过遵循常见的最佳实践来解决问题。 当我们必须处理必须执行某些操作的具有相同结构的多个对象时,访问者模式在场景中很有用。 访客可以通过将它们定义在一类中来使相关操作保持在一起(Gamma等,1995)。 当我们想影响访问者类的数据时,这为利用引擎的覆盖范围功能集提供了更多机会。

后记 (Afterword)

The implementation of the visitor pattern lacks the so-called common Apply method. This is done intentionally and considered unnecessary by me because the way the instances of the visitor classes are resolved satisfies the overall idea of the pattern. Of course, it is possible to add another level of abstraction in the character classes such as ArcherDamageSystem, ArcherStatsSystem that would in turn use the visitor classes and expose the Apply method, but I believe this is not the point here and ignoring Apply method is acceptable due to the circumstances.

访问者模式的实现缺少所谓的通用Apply方法。 这是有意完成的,我认为这是不必要的,因为解析访问者类的实例的方式满足了该模式的整体思想。 当然,也可以添加在字符类如ArcherDamageSystem,ArcherStatsSystem这反过来将使用访问者类和揭露应用方法另一层抽象的意义,但我相信在这里这并不是问题的关键,而忽略应用方法是可以接受的视情况而定。

翻译自: https://medium.com/the-innovation/visitor-pattern-in-unity3d-6f70f60db75d

unity3d 收费模式


http://chatgpt.dhexx.cn/article/CrRbO7Zl.shtml

相关文章

狼人杀微信小程序项目实例(附源码)

一、项目展示 狼人杀是一款多人参与的&#xff0c;通过语言描述推动、较量口才和分析判断能力的策略类桌面游戏 玩家人数适于4-18人参与 主要角色有&#xff1a;狼人 、预言家 、平民 、女巫 、猎人 、白痴 、守卫 、骑士等 同时还有众多的玩家形象 各角色的职能介绍 设置游戏…

python获取游戏窗口_python中pygame针对游戏窗口的显示方法实例分析(附源码)

本文实例讲述了python中pygame针对游戏窗口的显示方法。分享给大家供大家参考,具体如下: 在这篇教程中,我将给出一个demo演示: 当我们按下键盘的‘f’键的时候,演示的窗口会切换到全屏显示和默认显示两种显示模式 并且在后台我们可以看到相关的信息输出: 上面给出了一个简…

unity3d之按秒倒计时

image.png 按秒倒计时 自定义变量计时 在程序中定义变量来累计时间。 实例代码 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;public class textTimer : MonoBehaviour {// Start is called before the first frame …

【开发工具】如何使用JetBrains Rider更好的开发Unity程序

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客QQ群&#xff1a;1040082875 一、前言 JetBrains Rider是一款快速强大的C#编辑器&#xff0c;也就是俗称的IDE。有2500多项的智能代码检查与重构&#xff0c;更加迅速编写和零误差的代码。完美集成与Unity…

Unity制作类胡闹厨房游戏 KitchenChaos 笔记整理

本文章是油管上CodeMonkey的一个unity项目KitchenChaos的笔记整理&#xff0c;学习并整理这个项目主要是因为终于看到了一个比较完整地用到了unity的各种功能、风格较为清爽的、代码结构清晰的同时比较新的项目。在学习之后也确实有很大的收获&#xff0c;首先通过该教程第一次…

unity python热更新_Unity C#热更新方案 ILRuntime学习笔记(一) Hello World

一、ILRuntime介绍 问&#xff1a;什么是热更新? 答&#xff1a;软件在使用时就能实现更新的方式就叫做热更新。热更新无需用户重新下载安装或重启&#xff0c;在使用时即可更新&#xff0c;方便快捷体验良好。 问&#xff1a;什么是ILRuntime? 答&#xff1a;ILRuntime是一个…

基于mediapipe的动作捕捉和Unity的球棍模型同步

基于mediapipe的动作捕捉和Unity的球棍模型同步 所需环境python端unity端效果 所需环境 这是我所使用的环境 python3.9 安装mediapipe和opencv-python包 python和Unity通信使用socket Unity2021.3 python端 如何安装那两个包我就不说了&#xff0c;大家有不明白可以去百度 m…

unity 原型_使用Unity和React快速进行原型制作

unity 原型 Web applications are great way to quickly reach a lot of users without the hassle of native client installs and play store downloads. Web frameworks such as React allow page components to communicate and respond to user interaction much like tra…

使用 命令行/WinForm 来打包Unity可执行程序

使用 命令行/WinForm 来打包Unity可执行程序 前言一、编辑Editor打包工具1.编辑打包脚本2.Unity编辑器中样式 二、命令行调用Unity打包函数1.Unity命令行常用参数2.命令行调用静态打包函数 三、使用WinForm创建可视化操作界面1.可视化界面2.代码详细&#xff1a;①CmdHelper类&…

Unity + Jenkins自动打包 (二)构建Jenkins项目以及编写Python、Unity脚本

1、新建Jenkens项目 在上一篇中&#xff0c;完成了Jenkins的安装和初始化&#xff0c;以及权限设置。 查看上一篇&#xff1a;Jenkins安装 点此 现在打开浏览器&#xff0c;输入http://localhost:8081&#xff0c;当然&#xff0c;需要改成你自己设置的Jenkins端口号&#xff…

unity python服务器_Unity如何连接服务器: 一个简单的例子

Unity3D本身是用来做客户端的通用游戏引擎, 要建立网络连接的话, 其实需要使用的是C#本身的网络和线程模块, 即System.Net.Sockets & System.Threading. 本文中我做了一个简单的例子, 适合那些需要做Unity客户端连接服务器功能的人入门. 整体项目 客户端: 我做的项目主要是…

unity + python socket通信,自定义数据包

unity和python相互之间通过socket通信来发送自定义数据包是一个利用unity构建场景和通过python来做数据处理的方式&#xff0c;能够有效的利用两种不同语言的优势。 我已经将对应的操作封装为对应的一个模块&#xff0c;SocketTools.cs&#xff0c;我们先来看一下具体的代码用…

假设电话收费标准为: (1)国际长途1.00元/分钟,(2) 国内长途0.60元/分钟,(3)市话前3分钟0.20元,3分钟以后0.10元/分钟。现假设某话单文件中每条话单包含如下信息:通话日期(10

你好&#xff0c;帮我做个C语言题目 你好&#xff0c;我是Assistant。很高兴为您做题。 请提供题目的完整题面&#xff0c;并提供任何相关的输入、输出、约束条件等信息。 如果您有任何其他问题&#xff0c;请随时与我联系。我将竭诚为您服务。 897354667qq.com 假设电话收…

电商用户行为数据分析实战(MySQL +PowerBI)

目录 一、项目概况二、数据源三、数据清洗3.1 选择子集导入&#xff0c;匹配适合的数据类型3.2 列重命名3.3重复值处理3.4 缺失值处理3.5 异常值处理从timestamps字段中提取日期数据列查看日期列数据异常情况 四、数据分析4.1 整体购物情况&#xff0c;基于AARRR模型4.1.1 各字…

【业务数据分析】——十大常用数据分析方法

&#x1f935;‍♂️ 个人主页&#xff1a;Lingxw_w的个人主页 ✍&#x1f3fb;作者简介&#xff1a;计算机科学与技术研究生在读 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4a…

基于订单的数据分析

目录 项目背景 数据理解 指标维度 指标梳理 维度梳理 导入数据 数据预处理 数据格式整理 规范字段名 增加字段 简化地址 缺失值处理 异常值分析​ 重复值处理 数据分析 描述性统计 总体销售情况 周趋势、日趋势分析 产品价格分析 地区分析 转化率分析 总结…

大数据培训 | 电商用户行为分析之订单支付实时监控

在电商网站中&#xff0c;订单的支付作为直接与营销收入挂钩的一环&#xff0c;在业务流程中非常重要。对于订单而言&#xff0c;为了正确控制业务流程&#xff0c;也为了增加用户的支付意愿&#xff0c;网站一般会设置一个支付失效时间&#xff0c;超过一段时间不支付的订单就…

订单数据分析

订单背景 订单&#xff1a;对订单的预测不仅为了企业更好的制定物料采购计划、控制库存、提升生产效率、控制生产进度&#xff0c;还为了帮助企业更好的把控市场潜在需求&#xff0c;分析目前经营状态和未来发展趋势。 宽厚板材市场价格&#xff08;只能查询到近三个月的&…

关于订单功能的处理和分析

这两天看了一下RABC的权限管理处理&#xff0c;梳理了一下订单功能的表创建&#xff0c;界面&#xff0c;功能分析。 目录 RABC RBAC0模型 那么对于RABC模型我们怎么创建数据库表&#xff1f; 订单模块的梳理 RABC RABC说的是在用户和权限之间多一个角色&#xff0c;用户与…

订单数据分析-实战

1. 京东订单数据准备 1.1 京东订单数据介绍 2020年5月25日10%抽样数据大家电-家用电器-冰箱70K 1.2 数据清洗 缺失值处理 用户城市和省份信息有部分缺失&#xff0c;部分订单的订单中支付时间为空值数据逻辑错误格式内容一致性 import pandas as pd import numpy as np im…