用于Unity3D的等距插件(译文)
By robot-v1.0
本文链接 https://www.kyfws.com/games/isometric-plugin-for-unity3d-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 17 分钟阅读 - 8394 个词 阅读量 0用于Unity3D的等距插件(译文)
原文地址:https://www.codeproject.com/Articles/1274596/Isometric-Plugin-for-Unity3D
原文作者:BlackMATov
译文由本站 robot-v1.0 翻译
前言
It’s a story on how to write a plugin for Unity Asset Store, take a crack at solving the well-known isometric problems in games, and make a little coffee money from that, and also to understand how expandable Unity editor is. Pictures, code, graphs and thoughts inside.
这是一个关于如何为Unity Asset Store编写插件,如何解决游戏中众所周知的等距问题,如何从中获利的故事,以及如何了解Unity可扩展编辑器的故事.里面的图片,代码,图表和思想.
序幕(Prologue)
因此,那天晚上我发现自己几乎无事可做.来年对我的职业生涯并没有真正的希望(尽管与个人生活不同,但这是一个完整的故事).无论如何,我有了这个主意,想为自己写一些有趣的东西,虽然很个人化,但我自己却有一点商业优势(当您的项目对其他人感兴趣时,我只是喜欢那种热情的感觉,除了为您的雇主).而且所有这些都与我一直期待着检查Unity编辑器扩展的可能性,并查看其平台上是否有出售引擎自己的扩展的优点有关.(So, it was one night when I found out I had got pretty much nothing to do. The coming year wasn’t really promising in my professional life (unlike personal one, though, but that’s a whole nother story). Anyway, I got this idea to write something fun for old times sake, that would be quite personal, something on my own, but still having a little commercial advantage (I just like that warm feeling when your project is interesting for somebody else, except for your employer). And all this went hand in hand with the fact that I have long awaited to check out the possibilities of Unity editor extension and to see if there’s any good in its platform for selling the engine’s own extensions.) 我有一天专门研究资产商店:模型,脚本,与各种服务的集成.首先,似乎所有内容都已被编写和集成,甚至具有许多不同质量和细节级别的选择,以及价格和支持.因此,我马上将其范围缩小到:(I devoted one day to studying the Asset Store: models, scripts, integrations with various services. And first, it seemed like everything has already been written and integrated, having even a number of options of different quality and detail levels, just as much as prices and support. So right away, I’ve narrowed it down to:)
- 仅代码(毕竟,我是一名程序员)(code only (after all, I’m a programmer))
- 仅2D(因为我只是喜欢2D,而且他们在Unity中对此提供了不错的现成支持)(2D only (since I just love 2D and they’ve just made a decent out-of-the-box support for that in Unity)) 然后,我想起了当我们制作等距游戏时,我吃了多少仙人掌,死了多少只老鼠.您将不会相信我们在寻找可行的解决方案上花了多少时间,并且在尝试整理和绘制等轴测图时我们已经破坏了多少本.因此,我努力保持双手不动,我用不同的关键词和不太关键的词进行搜索,除了一大堆等轴测图艺术之外,找不到任何东西,直到我最终决定从头开始制作一个等轴测图插件.(And then, I remembered just how many cactuses I’ve eaten and how many mice’ve died when we were making an isometric game before. You won’t believe how much time we’ve killed on searching viable solutions and how many copies we’ve broken in attempts to sort out this isometry and draw it. So, struggling to keep my hands still, I searched by different key and not-so-much-key words and couldn’t find anything except a huge pile of isometric art, until I finally decided to make an isometric plugin from scratch.)
设定目标(Setting the Goals)
简而言之,我首先要描述的是该插件应该解决的问题以及等距游戏开发人员将如何使用它.因此,等距问题如下:(The first thing I need to describe in short is what problems this plugin was supposed to solve and what use the isometric games developer would make of it. So, the isometry problems are as follows:)
- 通过远程排序对象以正确绘制它们(sorting objects by remoteness in order to draw them properly)
- 在编辑器中创建,定位和移动等距对象的扩展(extension for creation, positioning and displacement of isometric objects in the editor) 因此,在制定了第一版的主要目标的基础上,我将自己设定为第一版草案的2-3天.因此,您不能因此而推迟,因为热情是一件易碎的事情,如果您在开始的几天没有准备好东西,那么您很有可能会毁掉它.新年假期并不是那么长,即使在俄罗斯也是如此,我想在十天内发布第一版.(Thus, with the main objectives for the first version formulated, I set myself 2-3 days deadline for the first draft version. Thus couldn’t being deferred, you see, since enthusiasm is a fragile thing and if you don’t have something ready in the first days, there’s a great chance you ruin it. And New Year holidays are not so long as they might seem, even in Russia, and I wanted to release the first version within, like, ten days.)
排序(Sorting)
简而言之,等轴测图是2D精灵尝试看起来像3D模型的尝试.当然,这会导致许多问题.最主要的是,必须按照绘制顺序对精灵进行排序,以避免相互重叠的麻烦.(To put it briefly, isometry is an attempt made by 2D sprites to look like 3D models. That, of course, results in dozens of problems. The main one is that the sprites have to be sorted in the order in which they were to be drawn to avoid troubles with mutual overlapping.)
在屏幕截图上,您可以看到首先绘制的是绿色精灵(2,1),然后是蓝色精灵(1,1)(On the screenshot, you can see how it’s the green sprite that is drawn first (2,1), and then the blue one goes (1,1))
屏幕截图显示了首先绘制蓝色精灵时的不正确排序(The screenshot shows the incorrect sorting when the blue sprite’s drawn first)在这种简单的情况下,排序将不会成为问题,并且会有一些选项,例如:(In this simple case, sorting won’t be such a problem, and there are going to be options, for example:)
- 按Y在屏幕上的位置排序,即(sorting by position of Y on the screen, which is)
(isoX + isoY) * 0.5 + isoZ
- 从最左边的等距网格单元从左到右,从上到下绘制(drawing from the remotest isometric grid cell from left to right, from top to down)
[(3,3),(2,3),(3,2),(1,3),(2,2),(3,1),...]
- 以及其他许多有趣而又不太有趣的方式(and a whole bunch of other interesting and not really interesting ways)
它们都是非常好的,快速的并且可以正常工作,但是仅在这种单单元对象或列扩展为(They all are pretty good, fast and working, but only in case of such single-celled objects or columns extended in)
isoZ
方向:)毕竟,我对更通用的解决方案感兴趣,该解决方案适用于在一个坐标方向上延伸的对象,甚至对绝对没有宽度但在与必要高度相同的方向上延伸的"栅栏"也适用.(direction :) After all, I was interested in more common solution that would work for the objects extended in one coordinate’s direction, or even the “fences” which have absolutely no width, but are extended in the same direction as the necessary height.)
屏幕截图显示了对扩展对象进行排序的正确方法(The screenshot shows the right way of sorting extended objects)3x1(3x1)和(and)1x3(1x3)用"栅栏"测量(with “fences” measuring)3x0(3x0)和(and)0x3(0x3)这就是我们的麻烦开始的地方,并将我们置于必须决定前进道路的地方:(And that’s where our troubles begin and put us in place where we have to decide on the way forward:)
- 将"多单元"对象拆分为"单单元"对象,即垂直切割对象,然后对出现的条纹进行排序(split “multi-celled” objects into “single-celled” ones, i.e., to cut it vertically and then sort the stripes emerged)
- 考虑一下新的排序方法,它更加复杂有趣(think about the new sorting method, more complicated and interesting) 我选择了第二种选择,没有特别的愿望去处理每个对象的棘手处理,切割(甚至自动)和逻辑的特殊方法.作为记录,他们在一些著名游戏中使用了第一种方式,例如(I chose the second option, having no particular desire to get into tricky processing of every object, into cutting (even automatic), and special approach to logic. For the record, they used the first way in few famous games like)辐射1(Fallout 1)和(and)辐射2(Fallout 2).如果您进入游戏的数据,则实际上可以看到这些带.(. You can actually see those strips if you get into the games' data.) 因此,第二个选项并不意味着任何排序标准.这意味着没有可以用来对对象进行排序的预先计算的值.如果您不相信我(我猜很多人从来没有使用过等轴测图),那就拿一张纸画一些小物体,像(So, the second option doesn’t imply any sorting criteria. It means that there is no pre-calculated value by which you could sort objects. If you don’t believe me (and I guess many people who never worked with isometry don’t), take a piece of paper and draw small objects measuring like)2x8(2x8)例如(and, for example,)2x2(2x2).如果您设法找到一个值来计算其深度和排序,则只需添加一个(. If you somehow manage to figure out a value for calculation its depth and sorting - just add a)8x2(8x2)对象并尝试将它们相对于彼此放置在不同的位置.(object and try to sort them in different positions relative to one another.) 因此,没有这样的价值,但是我们仍然可以使用它们之间的依赖关系(大致来说,哪个与哪个重叠)(So, there’s no such value, but we still can use dependencies between them (roughly speaking, which one’s overlapping which) for) 拓扑排序(topological sorting) .我们可以通过使用等距坐标在等距轴上的投影来计算对象的依赖性.(. We can calculate the objects' dependencies by using projections of isometric coordinates on isometric axis.)
屏幕截图显示了蓝色立方体依赖于红色立方体(Screenshot shows the blue cube having dependency on the red one)
屏幕截图显示了绿色立方体依赖于蓝色立方体(Screenshot shows the green cube having dependency on the blue one)用于确定两个轴依赖性的伪代码(与Z轴相同):(A pseudocode for dependency determination for two axis (same works with Z-axis):)
bool IsIsoObjectsDepends(IsoObject obj_a, IsoObject obj_b) {
var obj_a_max_size = obj_a.position + obj_a.size;
return
obj_b.position.x < obj_a_max_size.x &&
obj_b.position.y < obj_a_max_size.y;
}
通过这种方法,我们在所有对象之间建立依赖关系,然后在它们之间递归传递并标记显示Z坐标.该方法非常通用,最重要的是,它可以工作.您可以阅读此算法的详细说明,例如,(With such an approach, we build dependencies between all the objects, passing among them recursively and marking the display Z coordinate. The method is quite universal, and, most importantly, it works. You can read detailed description of this algorithm, for example,) 这里(here) 要么(or) 这里(here) .他们还在流行的Flash等距库中使用了这种方法((. Also they use this kind of approach in popular flash isometric library () as3isolib(as3isolib) ).().) 一切都很好,只不过这种方法的时间复杂性(And everything was just great except that time complexity of this approach is)O(N ^ 2)(O(N^2))因为我们必须将每个对象相互比较以创建依赖关系.我已经为以后的版本进行了优化,仅添加了惰性重新排序,因此在进行某些操作之前不会进行任何排序.因此,我们稍后将讨论优化.(since we’ve got to compare every object to every other one in order to create the dependencies. I’ve left optimization for later versions, having added only lazy re-sorting so that nothing would be sorted until something moves. So we’re going to talk about optimization little bit later.)
编辑器扩展(Editor Extension)
从现在开始,我有以下目标:(From now on, I had the following goals:)
- 对象的排序必须在编辑器中进行(不仅在游戏中)(Sorting of objects had to work in the editor (not only in a game))
- 必须有另一种Gizmos-Arrow(用于移动对象的箭头)(There had to be another kind of Gizmos-Arrow (arrows for moving objects))
- 可选地,移动对象时将与图块对齐(Optionally, there would be an alignment with tiles when object’s moved)
- 瓷砖的大小将自动应用,并在等轴测世界检查器中设置(Sizes of tiles would be applied and set in the isometric world inspector automatically)
- AABB(AABB) 根据对象的等距尺寸绘制对象(objects are drawn according to their isometric sizes)
- 通过更改对象检查器中的等距坐标的输出,我们可以更改对象在游戏世界中的位置(Output of isometric coordinates in the object inspector, by changing which we would change the object’s position in the game world) 所有这些目标均已实现. Unity确实确实允许相当大地扩展其编辑器.您可以在对象检查器中添加新的选项卡,窗口,按钮,新字段.如果需要,您甚至可以为所需类型的组件创建自定义检查器.您还可以在编辑器窗口中输出其他信息(在我的情况下,是在AABB对象上),也可以替换对象的标准移动小控件.通过这种魔术解决了编辑器内部排序的问题(And all of these goals have been achieved. Unity really does allow to expand its editor considerably. You can add new tabs, windows, buttons, new fields in object inspector. If you want, you can even create a customized inspector for a component of the exact type you need. You can also output additional information in the editor’s window (in my case, on AABB objects), and replace standard move gizmos of objects, too. The problem of sorting inside the editor was solved via this magic) ExecuteInEditMode(ExecuteInEditMode) 标签,该标签允许在编辑器模式下运行对象的组件,即与游戏中的运行方式相同.(tag, which allows to run components of the object in editor mode, that is to do it the same way as in a game.) 当然,所有这些工作并非没有各种困难和技巧,但是我没有花一个多小时来解决所有问题(Google,论坛和社区肯定可以帮助我解决所有问题出现,但文档中未提及).(All of these were done, of course, not without difficulties and tricks of all kinds, but there was no single problem that I’d spent more than a couple of hours on (Google, forums and communities sure helped me to resolve all the issues arisen which were not mentioned in the documentation).)
屏幕截图显示了我在等距世界中的运动对象的小控件(Screenshot shows my gizmos for movement objects within isometric world)## 发布(Release) 因此,我准备好了第一个版本,并截取了屏幕截图.我什至画了一个图标并写了描述.是时候了.因此,我将名义价格定为5美元,将该插件上传到商店中,然后等待Unity批准.我并没有考虑太多价格,因为我还真的不想赚大钱.我的目的是找出是否有一般需求,如果有,我想估计一下.另外,我想帮助等距游戏的开发人员,他们最终以某种方式最终被剥夺了机会和增加的东西.(So, I got the first version ready, took the screenshot. I even drew an icon and wrote a description. It’s time. So, I set a nominal price of $5, uploaded the plugin in the store and waited for it to be approved by Unity. I didn’t think over the price much, since I didn’t really want to earn big money yet. My purpose was to find out if there is a general demand and if it was, I would like to estimate it. Also, I wanted to help developers of isometric games who somehow ended up absolutely deprived of opportunities and additions.) 在5个相当痛苦的日子里(我花了相同的时间编写第一个版本,但是我知道自己在做什么,而没有进一步的思考和思考,与刚开始使用等距技术的人相比,这给了我更高的速度) ,我收到Unity的回应,说该插件已获批准,我已经可以在商店中看到它,以及零(到目前为止)的销售额.它在本地论坛上签到,在商店的插件页面中内置了Google Analytics(分析),并准备好等待草生长.(In 5 rather painful days (I spent about the same time writing the first version, but I knew what I was doing, without further wondering and overthinking, that gave me the higher speed in comparison with people who’d just started working with isometry), I got a response from Unity saying that the plugin was approved and I could already see it in the store, just as well as its zero (so far) sales. It checked in on the local forum, built Google Analytics into the plugin’s page in the store and prepared myself to wait the grass to grow.) 很快就进行了首次销售,就好像在论坛和商店上收到了反馈一样.在1月的剩余日子里,我的插件已售出12份,我认为这是公众利益的标志,因此决定继续进行.(It didn’t take very long before first sales, just as feedbacks on the forum and the store came up. For the remaining days of January, 12 copies of my plugin have been sold, which I considered as a sign of the public’s interest and decided to continue.)
优化(Optimization)
因此,我对两件事感到不满意:(So, I was unhappy with two things:)
- 排序时间复杂度-O(N ^ 2)(Time complexity of sorting - O(N^2))
- 有垃圾收集和一般性能的问题(Troubles with garbage collection and general performance)
算法(Algorithm)
有100个对象和O(N ^ 2),我需要进行10,000次迭代才能找到依赖关系,而且还必须传递所有这些对象并标记显示Z进行排序.对此应该有一些解决方案.因此,我尝试了很多选择,无法不考虑这个问题.无论如何,我不会告诉您我尝试过的所有方法,但是我将介绍到目前为止找到的最好的方法.(Having 100 objects and O(N^2), I had 10,000 iterations to make just to find dependencies, and also I’d have to pass all of them and mark the display Z for sorting. There should’ve been some solution for that. So, I tried a huge number of options, could not sleep thinking about this problem. Anyway, I’m not going to tell you about all the methods I’ve tried, but I’ll describe the one that I’ve found the best so far.) 首先,当然,我们仅对可见对象进行排序.这意味着我们经常需要知道拍摄的内容.如果有任何新对象,我们必须在排序过程中添加它,并且如果其中一个旧对象不见了,请忽略它.现在,Unity不允许确定对象的(First thing first, of course, we sort only visible objects. What it means is that we constantly need to know what’s in our shot. If there is any new object, we got to add it in the sorting process, and if one of the old one’s gone - ignore it. Now, Unity doesn’t allow to determine the object’s) 边界框(Bounding Box) 和它的孩子一起在场景树中.越过孩子(顺便说一句,每次都可以添加和删除孩子)是行不通的-太慢了.我们也不能使用(together with its children in the scene tree. Pass over the children (every time, by the way, since they can be added and removed) wouldn’t work - too slow. We also can’t use) OnBecameVisible(OnBecameVisible) 和其他事件,因为它们仅适用于父对象.但是我们可以得到所有(and other events because these work only for parent objects. But we can get all) 渲染器(Renderer) 必要对象及其子对象的组件.当然,这听起来不是我们最好的选择,但是我找不到其他方法,通用且性能可以接受.(components from the necessary object and its children. Of course, it doesn’t sound like our best option, but I couldn’t find another way, same universal and acceptable by performance.)
List<Renderer> _tmpRenderers = new List<Renderer>();
bool IsIsoObjectVisible(IsoObject iso_object) {
iso_object.GetComponentsInChildren<Renderer>(_tmpRenderers);
for ( var i = 0; i < _tmpRenderers.Count; ++i ) {
if ( _tmpRenderers[i].isVisible ) {
return true;
}
}
return false;
}
使用有一点技巧(There is a little trick of using)GetComponentsInChildren(GetComponentsInChildren)该函数允许在没有必要的缓冲区中分配内存的情况下获取组件,这与另一个返回新的组件数组的函数不同(function that allows to get components without allocations in the necessary buffer, unlike another one that returns new array of components)其次,我仍然需要做一些事情(Secondly, I still had to do something about)O(N ^ 2)(O(N^2)).在尝试将等距对象投影到显示空间中的简单二维网格之前,我尝试了多种空间拆分技术.每个此类扇区都包含一个与之交叉的等轴测对象列表.因此,想法很简单:如果对象的投影没有交叉,那么在对象之间建立依赖关系就毫无意义.然后,我们跳过所有可见的对象,仅在必要的部分建立依赖关系,从而降低了算法的时间复杂度并提高了性能.我们将每个扇区的大小计算为所有对象大小之间的平均值.我发现结果不仅仅令人满意.(. I’ve tried a number of space splitting techniques before I stopped at a simple two-dimensional grid in the display space where I project my isometric objects. Every such sector contains a list of isometric objects that are crossing it. So, the idea is simple: if projections of the objects are not crossed, then there’s no point in building dependencies between the objects at all. Then we pass over all visible objects and build dependencies only in the sectors where it’s necessary, thereby lowering time complexity of the algorithm and increasing performance. We calculate the size of each sector as an average between the sizes of all objects. I found the result more than satisfying.)
一般表现(General Performance)
当然,我可以为此写一篇单独的文章…好的,让我们尝试简短一下.首先,我们要兑现这些组件(我们使用(Of course, I could write a separate article on this… Okay, let’s try to make this short. First, we’re cashing the components (we use) 获取组件(GetComponent) 找到它们,这并不快).我建议大家在进行任何与之相关的工作时要保持警惕(to find them, which is not fast). I recommend everyone to watch yourselves when working with anything that has to do with) 更新资料(Update) .您始终必须牢记每帧都会发生这种情况,因此必须非常小心.另外,请记住所有有趣的功能,例如(. You always have to bear in mind that it happens for every frame, so you’ve got to be really careful. Also, remember all interesting features like) 自定义==运算符(custom == operator) .有很多事情要记住,但是最后,您会在内置探查器中了解其中的每一个.它使记忆和使用它们变得更加容易. :)(. There are a lot to things to keep in mind, but in the end, you get to know about every one of them in the built-in profiler. It makes it much easier to memorize and use them. :))
另外,您将真正了解垃圾收集器的痛苦.需要更高的性能?然后,忘记任何可以分配内存的内容,(Also, you get to really understand the pain of garbage collector. Need higher performance? Then forget about anything that can allocate memory, which in)C#(C#)(尤其是旧的((especially in old)单核细胞增多症(Mono)编译器)可以通过任何方式完成,范围从(compiler) can be done by anything, ranging from) foreach
(!)到新兴的Lambda,更不用说((!) to emerging lambdas, let alone)LINQ(LINQ)现在即使在最简单的情况下也禁止您这样做.最后,而不是(which is now prohibited for you even in the simplest cases. In the end, instead of)C#(C#)用它的句法糖,你看起来很像(with its syntactic sugar, you get a semblance of)C(C)具有可笑的能力.(with ridiculous capacities.)
在这里,我将提供一些有关您可能会有所帮助的主题的链接:(Here, I’m going to give some links on the topic you might find helpful:) 第1部分(Part 1) ,(,) 第2部分(Part 2) ,(,) 第三部分(Part 3) .(.)
结果(Results)
我以前从未听说过有人使用这种优化技术,因此看到结果特别高兴.如果在第一个版本中,游戏实际上需要50个移动对象才能将其转换成幻灯片显示,现在即使在一个框架中有800个对象时,它也可以很好地工作:一切都以最快的速度旋转并重新排序持续3-6毫秒,这对于等轴测中的此数量的对象非常有用.而且,初始化之后,它几乎没有为一个帧分配内存:)(I’ve never known anybody using this optimization technique before, so I was particularly glad to see the results. And if in the first versions, it took literally 50 moving objects for the game to turn it into a slideshow, now it works pretty well even when there’re 800 objects in a frame: everything’s spinning at top speed and re-sorting for just for 3-6 ms which is very good for this number of objects in isometry. Moreover, after initialization, it almost hasn’t allocated memory for a frame :))
进一步的机会(Further Opportunities)
阅读反馈和建议后,我在过去的版本中添加了一些功能.(After I read feedbacks and suggestions, there were a few features which I added in the past versions.)
2D/3D混合(2D/3D Mixture)
在等距游戏中混合2D和3D是一个有趣的机会,它可以最大程度地减少绘制不同的移动和旋转选项(例如,动画角色的3D模型).这并不是一件很难的事,但是需要在分拣系统中进行集成.您需要做的就是(Mixing 2D and 3D in isometric games is an interesting opportunity allowing to minimize drawing of different movement and rotations options (for instance, 3D models of animated characters). It’s not really hard thing to do, but requires integration within the sorting system. All you need is to get a)边界框(Bounding Box)模型及其所有子项,然后沿显示Z移动模型的框的宽度.(of the model with all its children, and then to move the model along the display Z by the box’s width.)
Bounds IsoObject3DBounds(IsoObject iso_object) {
var bounds = new Bounds();
iso_object.GetComponentsInChildren<Renderer>(_tmpRenderers);
if ( _tmpRenderers.Count > 0 ) {
bounds = _tmpRenderers[0].bounds;
for ( var i = 1; i < _tmpRenderers.Count; ++i ) {
bounds.Encapsulate(_tmpRenderers[i].bounds);
}
}
return bounds;
}
那是如何获得的一个例子(That’s an example of how you can get)边界框(Bounding Box)模型及其所有子级.(of the model with all its children.)
这就是完成后的样子(and that’s what it looks like when it’s done)### 自定义等距设置(Custom Isometric Settings) 那是相对简单的.我被要求设置等角,纵横比,瓷砖高度.在经历了数学上的痛苦之后,您会得到以下信息:(That is relatively simple. I was asked to make it possible to set the isometric angle, aspect ratio, tile height. After suffering some pain involved in maths, you get something like this:)
物理(Physics)
在这里,它变得更加有趣.由于等轴测图可模拟3D世界,因此物理学也应该是三维的,包括高度和所有要素.我想到了这个有趣的把戏.我复制了物理学的所有组成部分,例如(And here it gets more interesting. Since isometry simulates 3D world, physics is supposed to be three-dimensional, too, with height and everything. I came up with this fascinating trick. I replicate all the components of physics, such as) 刚体(Rigidbody) ,(,) 对撞机(Collider) 等距等距世界.根据这些描述和设置,我使用引擎本身和内置的副本制作了不可见的三维物理世界的副本.(and so on, for isometric world. According to these descriptions and setups, I make the copy of invisible physical three-dimensional world using the engine itself and built-in)物理X(PhysX).之后,我将计算出的模拟数据取回,并在等距世界的复制组件中取回这些数据.然后,我执行相同的操作来模拟碰撞和触发事件.(. After that, I take the simulation data calculated and get those back in duplicating components for isometric world. Then I do the same to simulate bumping and trigger events.)
工具集物理演示GIF(The toolset physical demo GIF)## 结语和结论(Epilogue and Conclusions) 在实施了论坛中的所有建议之后,我决定将价格提高到40美元,因此它看起来不像是带有五行代码的另一个便宜的插件. :)我将非常高兴回答问题并听取您的建议.我欢迎各种批评,谢谢!现在,我最后要保存的是该月的销售统计数据:(After I implemented all the suggestions from the forum, I decided to raise the price up to 40 dollars, so it wouldn’t look like just another cheap plugin with five lines of code. :) I will be very much delighted to answer questions and listen to your advices. I welcome all kinds of criticism, thank you! And now, something I was saving for last, the month’s statistics of sales:)
月(Month) | 5美元(5$) | 40美元(40$) |
---|---|---|
January | 12 | 0 |
February | 22 | 0 |
March | 17 | 0 |
April | 9 | 0 |
May | 9 | 0 |
June | 9 | 0 |
July | 7 | 4 |
August | 0 | 4 |
September | 0 | 5 |
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C# Unity3D Unity extension plugin 新闻 翻译