• Content count

  • Joined

  • Last visited

Community Reputation

182 Neutral

About Mizmoon

  • Rank

Personal Information

  • Interests
  1. Thanks! I knew this was the case for Equals, just wasn't sure about GetHashCode. Good to know!
  2. That's a great response Nypyren!! I didn't know about those early-exits in string.Equals, that's very interesting. Doesn't help much when the value will (ideally) always exist, though. Another quick question regarding hashing: let's say that i have an object where i'm not interested in knowing whether the objects are actually equal other than by reference (imagine hashing the bricks of a building - they are all identical, you just want to know which is which). Should i override GetHashCode() to only consider the reference (with some xor to distribute it), or is this an anti-pattern? Am i more likely to end up with a worse distribution than the default implementation?
  3. Hello! I'm working on a hobby game project where i have a static resource manager class which loads and maps all game resources into dictionaries, using their mod name (the game is moddable) and file name. For instance, for all meshes, you might have an entry like this: meshes[@"core/MyDebugMesh"] = LoadMesh(path); Where "core" is the default mod name of internal files. The string "core/MyDebugMesh" then occurs inside JSON files under the field "mesh" (or similar). I like this format because it is easy to work with and has acceptable guarantees in terms of key uniqueness (two files of the same type can't occupy the same path). The system automatically navigates through specified folders and figures out what to do with the files there. However, i read in the MSDN documentation that two different strings can have the same hash code, and also that the hash function produces different results on 32-bit and 64-bit machines. Is this something i need to be concerned about? Aside from this, are there any implications on performance using my solution?
  4. Hmm, when i calculate it, i get 40 bytes (12 per vector, 16 for a quaternion using 4 floats - assuming they are all structs). But i guess you're right. The reason i mentioned this is because i once asked a similar question (regarding block storage in a block builder game) and was told that even having a single reference to the block type was wasteful compared to having a type identifier int. Overall though i think you gain a lot more from having a system which is flexible and easy to understand.
  5.   Those '64 bit references' are presumably the same size as the function pointers in the vtable if you had a list of Missiles and needed to call virtual RocketXYZ functions on some of them. This isn't a valid concern unless you have thousands of these all existing at the same time and not many virtual functions by comparison. If you're 'rather new to game development' like you say then I humbly submit that you are mistaken in your concern here.   I don't necessarily have a problem with inheritance in this context - e.g. I would argue that a Shield and a Weapon are interchangeable for many purposes (they can be picked up, held in a hand, carried in inventory, dropped on the floor, bought and sold) but if you ever want to use a shield as a weapon (e.g. a shield bash attack) or want to combine other traits (e.g. is a wizard's staff a weapon or a wand-like magical artifact?) you often find yourself pulled back towards a single Item class with flags, properties and components defining how they operate.     The vtable saves a funciton pointer for each virtual method per class (each instance has one vtable pointer pointing to the same table), attaching three components rather than having one type id increases the memory overhead per instance from 32 to 384 bits (assuming they are doubly linked). However, if you say it is of no concern, i will trust your judgement on this.
  6.   Although i agree with everything you say, "ISA" means the exact same thing as inheritance. Weapon -> ISA -> Item is no doubt correct.   I really like component designs and tend to use them whenever i can, but the issue for me is that the performance tends to be worse for some purposes. For instance, if you create a missile projectile and need to add the components "RocketMovement", "RocketExplode", "RocketHoming", etc - you end up with a large amount of 64 bit references linking these together. Then again, the benefits can sometimes outweigh the disadvantages.
  7.   Thanks, that's a really nice link! It answers most of the questions quite well.     I think you misunderstand me here, the idea of the second method is that you deserialize item classes directly from XML into instances of the ItemType class. Inside the type class, you have a method for returning an instance of the Item object linked to the type. You can have an infinite number of items; do you mean that it's hard to add new properties to your item types?       The reason i mentioned the third option is because you can cut down the size of the reference by half. Let's say that you have a game revolving around large quantities of units, or a projectile class with few fields other than the type, where memory is a factor. In this case, a 32 bit int id value is a very efficient way of storing the link to the type. When loading in the types, you can simply have an incrementing counter for each type you add and use this as the id. When saving the game, in to a save file, you can use a more specific id (mapped to the "runtime id") to make sure that adding more types won't screw up the save. In theory, you could even use ushort values, but sadly things like memory alignment and ALUs being optimized for 32 bit ints mitigate the benefits of this.   Thanks for the tip on scriptable objects, i was not aware of these before, will check it out!     Oh, and an additional question - when saving the item classes, i was tempted to make a separate folder for each type containing all its resources, including a XML/JSON file for that specific type. Is this a good way to structure things, or is it more efficient to just have all types defined in a single long "ItemTypes.xml" file?
  8. I'm rather new to game development and have been thinking about the different options for saving item types in your game. I've seen some people do this, sort of clunky and strictly OOP approach:       My own preference is doing something more like this:     Or thirdly - more lightweight, but with the added disadvantage that you have to store redundant information:     Are any of these options to prefer over the other?
  9. Does anyone have an idea on this? How to best represent that a chunk coordinate is occupied by another block, which overlaps it?
  10. That's quite interesting, i've never heard of that method before. Either way, i think i'm settling with using chunks. A new problem though is how to represent that a grid location is occupied by another block. At first, i figured that just setting all occupied spots to point towards the block would do it, but that won't work since you need the block's array position to represent the position of the mesh in local space. Another way is to use an "occupied" or "indirect" block which contains the x,y,z grid coordinates to its parent block (3x32 bits worth of integer might as well be replaced by an object reference - but then we won't know its position. Perhaps it is acceptable to use short ints?). In this case, if a child block is hit by a projectile, you can use it to reference the parent block - and if the hit kills it, you can use its Vector3 bounds to access all child blocks and remove them (i've got an integer version of Vector3). Let me know what you think of this solution.         I understand this, but why not just create a static block instance called "Air", and then check "if (chunk[x,y,z] == null) return Block.Air"? You won't be manipulating the air anyways, and it probably won't have a mesh assigned to it. To me, storing air in memory feels like.... well, storing air. Unless your blocks are structs, in which case i guess you might as well store air since the memory is allocated anyways.
  11. While i'd understand this type of recommendation for a minecraft-like voxel game, where you'd have entire landscapes of blocks, i'm not sure if it's a big concern in my case. I'm actually not expecting to have more than 10,000 blocks in any given scene. If anything, i could compromise by having a static BlockTypes class which contains arrays for each property, and where you'd get a value by calling, say, BlockTypes.GetMaxHealth(blockId) etc, with blockId being an ushort. The important part is that the block types should should be easily generated from a JSON or XML file. Any ideas on how to generate block IDs in a way that doesn't ruin saves if you add a new block type?
  12. Thanks for all the good responses! I had a feeling that chunks were the better option, i was just hesitant considering that the main benefits from using 3d arrays come when you use them to store structs (since the blocks would be next to each other in memory). Regarding this:       When you say "empty" value, do you mean a null value or a filler object? I've noticed that a lot of people use "air" blocks (perhaps to avoid dealing with null pointers), but i'm not sure if it makes sense from a memory point of view.     Is the hash function just the sum of the vector elements? Because in that case, yeah, it's problematic to say the least.     My idea was to keep a "BlockType" class reference inside each block, and to create more specialized components by extending the block class. I was also planning to keep block groups (essentially lists) inside the main construct which keep track of categories such as propulsion blocks or weapon blocks.
  13. Hello everyone! I've been working recently with a block-based building game in Unity, akin to Robocraft or Crossout, but i can't make up my mind on which would be the best way of storing the blocks. The idea is that the game should be based around larger components with a distinct function, the amount of blocks per construct should be in the ranges of 20 to 500. The blocks will be classes rather than structs, since they need to be mutable (each has a health property, etc). It is also important to be able to access nearby blocks on the grid, and to do path traversals between blocks to see if they are connected. The blocks come in different sizes and dimensions (1x1x1, 2x2x6, etc). The smallest unit is 1 meter which corresponds to the int value 1.   Here are the alternatives i've been considering so far:   The chunk approach Basically, having a main object which contains a dictionary of "chunks" tied to positions (determined by chunk size), where each chunk is a 3d array of blocks. Accessing a single block would be done by calculating the modulo of the position in construct space with the chunk size to get the target chunk, and get the precise position from there. Accessing is fast, and the blocks themselves won't take much memory space, but you'll ultimately end up storing a lot of empty space. How large should the chunks be? Should empty space be filled with "air" blocks?   A dictionary of blocks Simply having a dictionary where a Vector3i is the key and the block is the value. Storage becomes compact but access is slow, and i'm not sure what the performance situation would be when the dictionary hashtable resizes. Given that the block count will be moderately low, it might be sufficient.   Individual coordinates for each block Unity is based around GameObjects, and each object by default has a transform. Let's say that i would use a GameObject for each block and make them children of the main construct - would this be easier to work with or just be a nightmare for performance? Accessing neighbors would probably involve short-distance raycasting and this in itself feels like an unprofessional solution. On the other hand, it feels like Unity is meant to be used this way.   Are there any other options for storing blocks in a useful way?
  14. Hello everyone!   I am trying to make a simple game where you can move a satellite across a flat map and have it shoot lasers down to the surface. Needless to say that it is not an accurate simulation - you can move it in whichever direction you choose, but it's movement has a lot of inertia. The movement is limited to the 2d plane.   Each satellite has a vector for position, velocity, and target coordinates. Each loop, the velocity is scaled by a friction factor (0.93). What i want to know is this: how can i calculate wether i should add thrust to the satellite without the velocity becoming so high that it doesn't have time to break (by friction) in the distance left to the target? I realize that calcuating it precisely will end up in a differential equation, so all i need is an approximate "max velocity" where it will no longer apply thrust, to avoid overshooting.   Any help is very appreciated!
  15. avoid ships colliding?

    I was having the exact same problem once, and my solution was to give each ship an offset vector which represented how much the ship had to deviate from its course. The vector was zeroed at the start of each AI pass, and then you go through all neighboring ships in range, and add the vector between them and your ship scaled by a factor determined by their distance to you. This means that if there is another ship at both your left and your right, and they are at equal distances, the net offset will be zero. If there is one behind you and one to your left, the offset will be to your upper right, etc. If you need the offset as an angle, it is quite easily done with some trigonometry, followed by adding the offset angle to the facing of your ship to get the new facing. You might have a problem in the case where two ships are on your front left and right, and the best path would be to pass between them (while the offset vector points backwards), but it should be possible to fix with some exceptions.   Sorry for the semi-necropost, i hope it works out for you.