Author Topic: Shrugger! Unity!  (Read 151398 times)

Offline Shrugging Khan

  • Hero Member Mark III
  • *****
  • Posts: 1,217
  • Neinzul Y PzKpfw Tiger!
Re: Shrugger! Unity!
« Reply #225 on: May 15, 2014, 07:36:30 am »
And yet another thing - I'm calling a lot of methods with strings as parameters, which are then compared to others - but I've heard it said that comparing strings is very inefficient. Would it make a significant difference if I replaced them all with enums?

To illustrate, I do a lot of
Code: [Select]
GUI_AddLine("WeaponsList", gun.name, gun.ammo.ToString());In which all present GUI elements have their names compared to "WeaponsList" to see whether such a thing already exists, then the weapon's name is compared to all the entries in the list to see if it's a duplicate. This kind of thing happens for all other sorts of affairs to - probably several hundred times per frame.

So...would replacing as many as possible of those string-based descriptions with enums à la
Code: [Select]
enum GUI_ElementType { WeaponList, NavigationData, FleetData, PlayerData }improve performance in any noticeable way?

Thankee for any help :)
The beatings shall continue
until morale improves!

Offline Draco18s

  • Resident Velociraptor
  • Core Member Mark V
  • *****
  • Posts: 4,251
Re: Shrugger! Unity!
« Reply #226 on: May 15, 2014, 09:19:33 am »
And yet another thing - I'm calling a lot of methods with strings as parameters, which are then compared to others - but I've heard it said that comparing strings is very inefficient. Would it make a significant difference if I replaced them all with enums?

Yes.  Enums are great.  You as a programmer still the the benefit of using Strings, but the computer can go and use integers.  Enums can even contain other values (like a class).

For instance, Minecraft uses an enum for material type, so you get things like:

ToolMaterial.DIAMOND.efficiency

Offline keith.lamothe

  • Arcen Games Staff
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 19,505
Re: Shrugger! Unity!
« Reply #227 on: May 15, 2014, 10:57:10 am »
Enums are massively more efficient than strings.

Generally speaking string comparison should only be done when really necessary (matching user input to something, for example), or when it saves you a lot of dev work and is only run a few times in the program.  Like I'll sometimes actually take an enum's .ToString() and check for .StartsWith("Deprecated_") or whatever on that string, rather than have a switch with cases for all the deprecated enum values (we often have to retain the deprecated ones to avoid breaking deserialization of old save game files), as that removes the need for me remember to do that for each one.  But it only has to do that string compare once per enum, at the very beginning of the program running so it doesn't really slow anything down.

It's also wonderful to be able to right-click an enum value and do "find all references" and you can see everwhere it's used in the code.  That's because the relationship is statically defined, in a way the compiler can understand, rather than the dynamic association implied by the string value, which has no "real" relationship with a particular weapon-type-data (or whatever) until runtime.


Btw, strings in general are the source of many performance gotchas.  No fault of theirs, really, they're doing a very specific job and they do it well.  But often programmers do not know what that job really is (providing immutable sequences of characters).

So, for instance, if you do a lot of string concatenation (basically using the + operator with string operands) you're probably causing a metric ton of transient heap allocation, theoretically as bad as n^2 where n is the length of the string.  Where if you used a character buffer (the framework's StringBuilder is acceptable, though one can do better) it's often just n*2, particularly if you can predict the final length ahead of time.

Doesn't mean every single string.concat should be converted to a buffer instead (that would consume unnecessary developer time and not gain much in a lot of cases), but something to know about if you didn't already.  Of course, it 's possible we already had that discussion earlier in this thread ;)
Have ideas or bug reports for one of our games? Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline Shrugging Khan

  • Hero Member Mark III
  • *****
  • Posts: 1,217
  • Neinzul Y PzKpfw Tiger!
Re: Shrugger! Unity!
« Reply #228 on: May 21, 2014, 11:17:46 am »
Gradually phasing out all the strings in favour of enums; where possible. Thanks for the advise :)

Also once again fixed the sounds to cause less ear bleeding, did some work on the mouseover information and icon-accompanying text, and generally changed a lot of completely under-the-hood things. When will I ever get around to putting in new content?

Right now my project is breaking up the giant classes (Component, Resource, Crew), because I noticed their sheer size being the greatest deterrent to my working on exactly those things (machine functionality, resource handling and crew AI).

Is it a smart Idea to have the following setup?

Component:MonoBehaviour is the main component script - attached to a physical GameObject -, and mostly exists to contain multiple abstract SubComponents, each of which is inherited by a specific device (scAutoloader, scPump, scThrustVectoring, etc.). The latter classes mostly provide functionality, such as Autoloaders ejecting spent shells and loading new ones, Pumps moving liquids and gases from one component to another, and Thrust Vectoring changing the direction the nozzle of a propulsion system points in. SubComponent provides structural information like mass, volume, durability, temperature and so on.

Not sure if that's even the right way to describe it, but I'll happily hear your negative judgement on it if that's what it deserves.
The beatings shall continue
until morale improves!

Offline keith.lamothe

  • Arcen Games Staff
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 19,505
Re: Shrugger! Unity!
« Reply #229 on: May 21, 2014, 11:24:04 am »
Component:MonoBehaviour is the main component script - attached to a physical GameObject -, and mostly exists to contain multiple abstract SubComponents, each of which is inherited by a specific device (scAutoloader, scPump, scThrustVectoring, etc.).
We only actually have one MonoBehaviour (the camera) and it does everything.  Though I understand you're using the individual game objects so you can have Unity tell you when they're slamming into each other and such (iirc).

On the class hierarchy, I'm not sure I understand what you mean.  Is it something like this:

class Component
{
List<SubComponent> SubComponents;
}

abstract class SubComponent
{
}

class Autoloader : SubComponent
{
}

class Pump : SubComponent
{
}

class ThrustVectoring : SubComponent
{
}

?

Or something else?
Have ideas or bug reports for one of our games? Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline Shrugging Khan

  • Hero Member Mark III
  • *****
  • Posts: 1,217
  • Neinzul Y PzKpfw Tiger!
Re: Shrugger! Unity!
« Reply #230 on: May 21, 2014, 11:52:57 am »
Precisely so!

And yeah, I'm using MonoBehavior mostly just for the physics.
The beatings shall continue
until morale improves!

Offline keith.lamothe

  • Arcen Games Staff
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 19,505
Re: Shrugger! Unity!
« Reply #231 on: May 21, 2014, 12:06:08 pm »
Ok, I don't see anything particularly wrong about using inheritance for that.

We don't use it that way for our core-sim stuff (we use inheritance heavily in our GUI stuff, where there are relatively few objects and relatively many widely-distinct concepts) to avoid the overhead, and also because the intellisense often works better if it's not having to plow through virtual function tables.  It's also generally less code our way, I think.

So in our case we would do (and this isn't a suggestion, just fyi) :

class Component
{
List<SubComponent> SubComponents;
}

enum SubComponentType
{
None,
Autoloader,
Pump,
ThurstVectoring,
Length
}

class SubComponentTypeData
{
SubComponentType Type
}

class SubComponent
{
SubComponentTypeData TypeData
}

Where the type-data class would only have one instance per SubComponentType value (other than Length) that is instantiated during app-load and would contain the "invariant" info on that kind of subcomponent.  The SubComponent class would have potentially many instances (instantiated whenever needed, during the sim), and would contain the mutable information, and would be what was actually serialized to disk/network when being saved/sync'd, etc.
Have ideas or bug reports for one of our games? Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline Shrugging Khan

  • Hero Member Mark III
  • *****
  • Posts: 1,217
  • Neinzul Y PzKpfw Tiger!
Re: Shrugger! Unity!
« Reply #232 on: May 29, 2014, 07:44:26 am »
It mostly works now, except for one little issue.

I'm creating the subcomponents in a factory class to pass them to the component class, à la component.AddSubcomponent(subcomponent). Now, as previously stated, those abstract subcomponents are inherited by a variety of specific classes such as scInfraredSensor, scThrustVectoring or scAutoloader. When how can I, within the AddSubcomponent class, check what the specific class of the subcomponent is?

Thanks for any help, Google didn't present me with a solution so far ;P

PS: More specifically, I'm trying to get GetType() and typeof() to play nice, but comparing the two always returns false :/
PPS: Also played around with equals() and is, to no avail.
PPPS: Nevermind. ALL of the methods I tried worked, I just made a copypasting error.
« Last Edit: May 29, 2014, 09:24:31 am by Shrugging Khan »
The beatings shall continue
until morale improves!

Offline keith.lamothe

  • Arcen Games Staff
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 19,505
Re: Shrugger! Unity!
« Reply #233 on: May 29, 2014, 09:31:44 am »
Sounds like you figured it out :)  I generally use "is" if I must check a type in production code (and I avoid that outside GUI or possibly other low-frequency code).

I'm not sure if it's actually a well-founded-concern, but my concern with type checking is that it will incur some of the overhead usually associated with reflection.

So having that enum in our pattern helps there, as that's just an integer-equality test.

But since I haven't actually measured the performance of the two side-by-side I dunno if it's a big deal.
Have ideas or bug reports for one of our games? Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline NichG

  • Full Member
  • ***
  • Posts: 125
Re: Shrugger! Unity!
« Reply #234 on: June 07, 2014, 12:32:15 pm »
Getting back to Orbital Mechanics, I've started taking the hard route and doing it the KSP way - writing a separate physics system for them. The problem comes in the interactions between the Orbital Physics and the Rigidbody Physics.

1. How can I make Rigidbody interactions have proper effects on the Orbit? Difficulty: Adjusting the orbit to small collisions and thrust. I have a theory that I should just track the changes in velocity from one frame to the next and consider that kinetic energy, but I'd also have to subtract the orbital motion from that, and oyoyoy...

2. How can I let Orbital changes and Gravity have the right effects on the Rigidbodies? Difficulty: I somehow suspect that rigidbodies don't take kindly to being constantly pushed around by non-unity-physics forces, since I've already seen some strange behaviour when a rigidibody in motion was translated between two frames and it ended up somewhere it didn't expect to be.

I'm not sure about how this should work with Unity in particular, but essentially what you're doing by putting the object on a on-rails orbital track is you're splitting its total motion/physics into two pieces. One piece comes from the solution of the equations of motion for an object under the effect of gravity; the other piece comes from whatever detailed motions the object performs due to collisions/rotation/etc within the context of that orbiting reference frame.

One way to think about the orbiting reference frame is that its a choice of reference frame such that the fictitious force due to the frame's acceleration exactly counter-balances the force of gravity, so the motion of a single rigid object within the orbiting reference frame is in free-fall (e.g. you don't need to worry about gravity because its taken care of by choosing the orbiting reference frame).

Once you have two objects, the problem is that they are in slightly different orbits, so if you go to a shared reference frame containing both objects then the result is that gravity once again matters and needs to be calculated carefully. As far as I'm aware, KSP uses 'on-rails' orbits only when objects are not interacting, and when they are interacting it switches to something in which gravity/etc are fully taken into account - that's why objects sometimes jump around when you enter non-physics-timewarp.

What you can in principle do is to create a 'center of mass orbit frame' when two objects come near to eachother. This is basically the orbit of the average of the objects' motions. However, there isn't that much mathematical benefit in doing so because you still are going to have to take into account differential gravity (e.g. tidal forces) due to different distances within the frame from the primary. Of course if the interaction range is much smaller than the distance to the primary, you may choose to just assume that these tidal forces are zero.

When objects left collision distances of eachother, you'd then recalculate their individual orbits and update their orbital parameters.

Quote
3. Orbits require large, massive bodies, which greatly increases the distances in play. Even if it's just an earthlike 15,000 km or so, I'm guessing that the physics simulation will get pretty wonky that far away from the origin...

Double precision means that roughly speaking you've got 12-14 orders of magnitude of smooth resolution and then a few orders of magnitude that may have small, visible glitching. So with double-precision floating points you can resolve motions on the order of millimeters while still retaining distances of the order of 15000km. Its generally better however to separate things into two parts if there's a huge gap in the numbers like that - store the 'orbital-scale' numbers in one variable while storing the local position of sub-objects and nearby objects relative to their shared center-of-mass or something like that. That way, you don't have the issue that a 15000km orbit screws up the millimeter-scale rigid body stuff. Separating out the orbital physics like you're intending to should help you do this, though you'll have to be careful at the point where the two scales intersect (e.g. asking whether or not two orbiting objects are within 1km of eachother to initialize the detailed positional information).

Quote
A separate issue is that I have no idea on how to actually calculate orbital mechanics. If anyone knows a good page to read - this non-mathematician would be quite grateful.
I don't want to open the can of worms that is writing an all-new physics engine, unless you really think that's the best way ;P

And obviously none of this is anyone's speciality here, so miscellaneous input is just as appreciated as qualified knowledge  :D

The idea with orbital mechanics is that you can separate out the shape of the orbit (a particular ellipse or hyperbola) from your position along the orbit. Calculating the specific position that corresponds to a specific time still requires numerical integration or solving a transcendental equation, but the benefit is that basically you're always just solving versions of the same problem and so the error doesn't grow with time.

It looks like 'Orbital Elements' is one of the keywords to search for in finding information about this kind of thing. What you're going to want is a way to calculate orbital elements given 'orbital state vectors'. There's a stackexchange for this particular question which might help:

http://space.stackexchange.com/questions/1904/how-to-programmatically-calculate-orbital-elements-using-position-velocity-vecto

The other part you need is to be able to calculate the time evolution of the angle around the orbit. To do this you need to solve the equation for the 'true anomaly'. It seems like this is generally done by starting with the 'mean anomaly' M, which is the fraction of the orbital period that has passed since perigee (so sort of like an interpolating parameter). This is then related by a pair of transcendental equations to the true anomaly:

M = E - e sin(E) (the 'e' here is eccentricity; you want to solve this for E)
cos(E) = (e + cos(nu))/(1+ e cos(nu)) (the 'nu' here is the true anomaly, which is basically the angle around the orbit; you want to solve this for nu)

This page discusses it in more detail and gives a handy approximation, depending on how accurate a solution you need: http://www.braeunig.us/space/orbmech.htm


Offline Shrugging Khan

  • Hero Member Mark III
  • *****
  • Posts: 1,217
  • Neinzul Y PzKpfw Tiger!
Re: Shrugger! Unity!
« Reply #235 on: June 07, 2014, 05:41:30 pm »
Who are you, where have you come from, and what in the name of god made you read my thread?  :o

That said, thanks for the tips. I'm still tinkering around with the abstract model, and trying to read up on orbital simulations - I really need to give the links you posted a good looking-at, since I'm pretty short on good resources.

One thing I have to ask you right away though: Unlike KSP, this here can't get away with having close-in physics just within 1 or 2 kilometres from the POV. Engagements happen at up to several hundreds of kilometres, with multiple such engagements taking place at various locations within the scene. All of those require proper physics, all at the same time. The testing I've done so far has given me jittery physics from about 2000km out from the origin.

Obviously, using double precision would give me a lot more room, but AFAIK Unity insists on doing its coordinate and physics stuff in single precision floats. Damn them! Scaling the whole game down doesn't work (naturally), and moving the whole world relative to the POV also isn't a solution because it's not player-centric.

So right now I'm kinda afraid the only solution is to force the POV to stick to a particular engagement and simulate everything that's further away as an abstraction. Or ditching Unity. Meh.

--------------------------------------
In other, better news:
  • Having gained a few levels in my logartihmics skill, I was able to fix my SI unit converter to handle square and cubic values correctly.
  • Having also taken a level in inheritance, I'm slowly working my way through all the component types to slip them into sensibly manageable sub-components
  • And I keep on hunting string comparisons, day in, day out. Enum prevails!
The beatings shall continue
until morale improves!

Offline NichG

  • Full Member
  • ***
  • Posts: 125
Re: Shrugger! Unity!
« Reply #236 on: June 07, 2014, 10:45:02 pm »
Who are you, where have you come from, and what in the name of god made you read my thread?  :o

Just a wandering physicist noticing a thread asking about orbital mechanics :)

Quote
That said, thanks for the tips. I'm still tinkering around with the abstract model, and trying to read up on orbital simulations - I really need to give the links you posted a good looking-at, since I'm pretty short on good resources.

One thing I have to ask you right away though: Unlike KSP, this here can't get away with having close-in physics just within 1 or 2 kilometres from the POV. Engagements happen at up to several hundreds of kilometres, with multiple such engagements taking place at various locations within the scene. All of those require proper physics, all at the same time. The testing I've done so far has given me jittery physics from about 2000km out from the origin.

Obviously, using double precision would give me a lot more room, but AFAIK Unity insists on doing its coordinate and physics stuff in single precision floats. Damn them! Scaling the whole game down doesn't work (naturally), and moving the whole world relative to the POV also isn't a solution because it's not player-centric.

So right now I'm kinda afraid the only solution is to force the POV to stick to a particular engagement and simulate everything that's further away as an abstraction. Or ditching Unity. Meh.

Yeah, this is troublesome. The best I can suggest would be to figure out a way to treat each engagement as a separate Unity scene and then pull that data over to render in a 'fake' scene that is used only to establish the POV. I don't know how feasible that is though.

Offline Draco18s

  • Resident Velociraptor
  • Core Member Mark V
  • *****
  • Posts: 4,251
Re: Shrugger! Unity!
« Reply #237 on: June 07, 2014, 11:37:02 pm »
Yeah, this is troublesome. The best I can suggest would be to figure out a way to treat each engagement as a separate Unity scene and then pull that data over to render in a 'fake' scene that is used only to establish the POV. I don't know how feasible that is though.

You wouldn't be able to.  A "scene" in Unity is "everything going on right now."  An unloaded scene is like an ejected DVD: can't read, can't write.

Offline Shrugging Khan

  • Hero Member Mark III
  • *****
  • Posts: 1,217
  • Neinzul Y PzKpfw Tiger!
Re: Shrugger! Unity!
« Reply #238 on: June 08, 2014, 02:54:03 am »
Not to mention that engagements, as they currently are, really aren't separate entities - a powerful scout ship sitting next to one such engagement might be providing long-range sensor support to ships floating around somewhere else entirely, long-range precision weapons might be used from one end of the theatre to the other, fleet communications are all over the place anyways and if I really were to split things up into smaller chunks, then where will all the poor little stray shots go? They'd never be able to accidentally do a "Debris incoming" situation on anyone! D:

Edit: Right, orbits. Almost forgot! So ATM I'm thinking we might really simulate the orbits, with celestial bodies being completely on-rails sans physics. The active scene would be limited to about 1000-3000km, and anything travelling further out would be abstracted, put on rails, have only occasional AI checks to see whether they want to (and are even able to) do anything about their orbit, and be reintroduced to the active scene only if their orbits carry them back in or if the AI somehow makes it back under its own power. How to do interactions between on-rails AI entities...I dunnoe, yet.
« Last Edit: June 08, 2014, 03:00:57 am by Shrugging Khan »
The beatings shall continue
until morale improves!

Offline NichG

  • Full Member
  • ***
  • Posts: 125
Re: Shrugger! Unity!
« Reply #239 on: June 08, 2014, 01:08:45 pm »
What's the scale on which you actually need to resolve the interaction between game objects, versus the scale you need to render smooth motion to the player? E.g. if you rounded everything off to the nearest 10 meters for things like sensor ranges, weapon ranges, etc, would that be okay?

Because if so, what you can do is use a much coarser representation for the physics parts of the game (essentially your own engine, separate from Unity's, which would mean you could get around many of these problems), and then just use the RigidBody stuff and actual objects in scene for the purposes of rendering convincing motion - that is to say, you only do this for things near the point of view.

This may also help make things computationally less expensive. I don't know how important detailed rigidbody physics is going to be to engagements though.