Where to do the collision detection - c#

this is a question I've had for a while but never bothered asking.
Imagine I have 2 objects. 1 static, and the other movable (by player).
Where would the collision logic exist for that?
To elaborate; in my state I have a list of Components. These can be NPCs, static objects, the player, and just about everything being
private List<Component> _gameComponents;
If I were to do the check in the Player class, surely the player would need to know of the _gameComponents list, and then I'll do the check as I update so I can change the velocity accordingly.
Is there a standard I'm missing?
EDIT 1: I have just read that I should have a step between update and render for checking all collision. I'll give that a try, and see what happens.

Let every component that can be physically processed inherit from a custom interface like ICollidable.
Store every ICollidable in a List<T> that is separate from your components-list. And every ICollidable that is not static in even a third collection.
Have a third class that just processes the whole physics-part of your game and iterates through the non-statics-list. This way you only update what can be moved and you can compare it to every object that is in the list that contains every ICollidable.
Make sure you only check collision for objectes that are within the range of a moving object. It makes no sense to check a collision for an object that won't collide.
I always check for collisions before update, try what works best for you.

Related

How can I grab a reference of a game-object in a scene from a prefab

currently I am working on a Equipment system that will Instantiate Game objects into the scene from a list, prior to this I was not using a Instantiation system with just keeping the Game Objects Active in the scene at all time.
Now with Instantiating the Game Object(Prefab) I am running into the error of Loosing the References when I instantiate them, I have looked at various other articles before such as this Discussion here:
However I am looking at alternative ways other than using Tags as this system may use a large amount of tags decreasing game performance overtime, would anyone know different methods as to saving references from a scene into a prefab?
So as this is a new system I am really just looking for suggestions on how to save references of scene game-objects into a prefab, as my old system was just holding the game objects active in the scene and not actually instantiating them, once again I would love to hear different types of methods, something more than just using Tags.
The References im trying to save are three Transform Elements from a script attached to my Prefab they are the following
public Transform camPos;
public Transform aimLocation;
public Transform crosshairLocation;
Currently I am just dragging and dropping the gameobjects from the scene into the public fields in the script
Since this will be a major system I would like to not want to use tags for this system. But it is definitely a Valid option I am just looking for other methods for saving references of scene game-objects into a prefab When Instantiating the prefab into the scene,
Thank you for taking the time to read and any suggestions would be greatly Appreciated!
Any Questions Just Ask!
You can not save scene references in prefabs, for obvious reasons (what happens if you instantiate that prefab into another scene?). Your prefab needs to discover the objects it needs after it's instantiated. I'm not a huge fan of the tag system in Unity (or any other system that uses strings as identifiers, too much room for error). I'd recommend you take any of these three approaches:
Make the transforms you need (cam pos, aim location, etc.) singletons if there's ever only going to be one of each. You'd make a script class specifically for each one, make that class a singleton, and put it on the game objects. Then, after your prefab is instantiated, you can do something like this: camPos = CamPos.Instance.transform; You can read up on the singleton pattern here.
If there's going to be more than one of each, group all related objects into a single hierarchy (that is, make them all the child of a single game object). For example, if there are going to be many characters and each is going to have a separate aim location, you can make aim location a child of the character game object. Then, in your prefab (take care to make the prefab a child of the same root game object as well), you can do something along these lines: camPos = transform.root.GetComponentInChildren<CamPos>().transform; Better yet, you can have a component that has references to all such objects, and attach one to the root game object. Then, you can do: camPos = transform.root.GetComponent<ReferenceRepository>().CamPos;
Initialize the prefabs when they're instantiated. For example, say you have a player class that instantiates a weapon and already has a reference to the camPos. You can do it like this: var weapon = Instantiate<Weapon>(myWeaponPrefab); weapon.CamPos = camPos; Note however that when you assign public fields this way, they will only be accessible once Start is called. In other words, they won't be available in Awake.
That said, I don't think making stuff like aim location and crosshair location separate objects is a very good idea anyway. You should have a player/human/pawn class, and that class can provide this information to other objects that need it.

Loading objects instantiated during runtime from one scene to another in Unity

I'm creating a game where the player creates objects (blocks) in a "set up" scene and then when the timer ends, I'd like those objects, including their transform values to be loaded into a new scene. How would I go about loading objects created during runtime into a new scene?
DontDestroyOnLoad is a valuable way to achieve this.
What you could also do is the following:
Create an Empty object called "Cross-Scene-Objects" and add a script to it, make it so it doesn't destroy on load. Then simply child any objects to that object, and remove objects as you see fit.
You could also make the CrossSceneObjects script a singleton class and have some basic AddObject and RemoveObject methods which handle putting the game objects under the object.
If you only want certain objects in certain scenes, you could use the method above but add some further logic to set game objects active if you're in the scene you want them to show up in.
I have no example code, but if this is not enough for you to work off I can happily edit to provide code examples :) My style is to first provide the solution steps rather than the code to give you a starting point.

C# / Unity - Need help debugging my Chess program - trouble creating instance of class within another instance of the same class

I'm creating a Chess program. I've decided to make it so that, when a piece is selected, all of its possible legal moves are displayed. In order for that to work, I have to have a mechanism to predict the outcomes of moves (because you can't make a legal move which puts your own king in check, for example). This will also be useful when I start working on computer opponents, since the AI will need to be able to see several turns in advance in order to make intelligent decisions.
To this end, I've made it so that, at the start of each turn, all possible moves are calculated for the player's pieces, and then each of those possible moves is simulated to see whether or not it leaves the King in check. If so, that option is removed. I have a main class called BoardManager which controls the visuals and contains the actual chess board layout (in a ChessBoardSim), and I have a class ChessBoardSim, whose objects each contain one possible board state. ChessBoardSim can create other instances of ChessBoardSim, allowing the state of the board any number of turns in advance to be simulated.
I have a bug which I've been struggling with for over 5 hours, which appeared after I tried to restructure a lot of the code. I'm at my wit's end, and I just need a fresh pair of eyes. The issue is making it so that pieces aren't being removed from their old positions when moved, and the locations of some of the pieces on the board seem to be shifted two tiles up. I believe, based on the debugging, that the problem is appearing in CalculateAllMovementOptions() in the ChessBoardSim class - for some reason, when a ChessBoardSim has a ChessBoardSim child and the CalculateAllMovementOptions() function is called in the child, it changes the data in the parent.
I've included the full code below, and I'll describe the specific issue as best I can.
The flow of the problem is:
1: private void Start() in BoardManager is called.
2: The program draws and populates the board properly. A ChessBoardSim (called ChessPieces) is created to contain the data of the current board state.
3: StartTurn() is called in BoardManager, in order to begin the game.
4: StartTurn() calls ChessPieces.CalculateAllMovementOptions(). The intended function of CalculateAllMovementOptions() is to get back an array of Lists. Each List in the array contains the legal moves of one of the player's pieces. However, this actually seems to be changing the actual board data, and I can't work out why.
When a player tries to move a piece, the game breaks because the pieces aren't where they're supposed to be and the software can't cope with it. The piece which is moved doesn't remove itself from its old location (despite my best efforts), and this causes there to be two instances of that object, leading to an indexoutofrange exception when a piece of the code tries to access the 17th element of an array with 16 elements.
I would really appreciate it if anyone could help me, I feel like I've wasted an entire day on this already and I'm sure I'm missing something simple.
The link to my code is https://github.com/FC123321/Chess
Array.Clone doesn't create a deep copy of an array, so when you call boardLayout.Clone() in SimulateBoard (and again in the ChessBoardSim constructor), you are copying the references in boardLayout to the new array. This means that the pieces in the new array are the same object in the old one.
This means that when you're in MovePiece in SimulateBoard and you call piece.SetPosition and such on members of that copied array, you're setting the position of the pieces in the source of the copy as well.
Instead of using boardLayout.Clone(), you need to loop through the whole source array, and do newBoardLayout[x,y] = new ChessPiece(); and then copy over the values to the new ChessPiece. Alternatively, you could create a new ChessPiece constructor that takes another chess piece and copies the values there:
// ChessPiece copy constructor
public ChessPiece(ChessPiece other) {
this.Position = new int[2] { other.Position[0], other.Position[1]};
this.isWhite = other.isWhite;
this.movementType = other.movementType;
this.hasMoved = other.hasMoved;
this.turnDoubleMoved = other.turnDobleMoved;
}
// instead of boardLayout.Clone() in the ChessBoardSim constructor:
for (int x=0 ; x<8;x++){
for(int y=0; y<8;y++){
if (boardLayout[x,y] != null)
this.boardLayout[x,y] = new ChessPiece(boardLayout[x,y]);
}
}
// In SimulateBoard, take out the redundant Clone call
ChessBoardSim simBoard = new ChessBoardSim(boardLayout, turnNumber);

Unity 5 C# - How to Change Scenes and Import all Resources from Last Scene

I'm not sure how to switch scenes and bring all of my resources with me. I do understand that upon load of new scene, the previous scene gets destroyed on load. I've explored some with DontDestroyOnLoad() but had no luck with what I'm trying to do.
I tried to make my player controller a prefab and simply put him into the next scene; however, I returned a heck of a lot of errors because of the many scripts I have. Mostly stuff like checkpoint, HP bars, and even the weapon.
What I need to know is how to import everything into the next scene. How do I do this without having to recode or even re-make all of the stuff that I need?
You're looking for LoadSceneMode.Additive. This is the second parameter of the LoadScene method and will load the new scene into the current one.
If you need to import every object from the previous scene, then what's the point in creating a new one?
What you could do is saving the objects positions into a file and then loading that file back on the next scene or try (again) with DontDestroyOnLoad();
I recommend to check the documentation of Unity about this function.
If you want an individual object not to be destroyed on the scene change then on the void Awake() function of Unity make a DontDestroyOnLoad(this.gameObject);
Could you provide more information? I ask because it seems from your description that
DontDestoryOnLoad
should accomplish what you want but you say it does not. As long as the object holding the components whose states you want to save is persisted into the next scene using that method, then all of those components' states should be persisted as well. Please elaborate and we can possibly provide a better answer. As for how to use it to save the state of every game object:
GameObject[] allObjects = UnityEngine.Object.FindObjectsOfType<GameObject>();
foreach(GameObject go in allObjects) {
if (go.activeInHierarchy) { /* and any other logic you want. Maybe like !isTerrain */
Object.DontDestroyOnLoad(go);
}
}
For the above code, I ripped it from https://answers.unity.com/questions/329395/how-to-get-all-gameobjects-in-scene.html

Pacman Game Organization (XNA) - Where/how should I check for collisions with ghosts/food?

I have my Pacman game working, and i'm trying to go back through it and "organize" my code better. Before, I had this "TopObject" which referenced the object in game1.cs which basically referenced every object in my game (pacman, ghosts, map, etc). I made it globally available from ANYWHERE so that I could access my Pacman object from my ghost objects, or my map/tile objects from my ghost objects, or even my ContentMananger from anywhere to load content.
I know this is bad practice, so i'm trying to eliminate it. For instance, I created LoadContent() methods on all my objects which take a "ContentManager" type, which eliminated the need for me to call ContentManager using my TopObject.
Proceeding further, i'm having a really hard time doing stuff without this global reference to all my objects. For instance:
- From within my Pacman Update()..
I need to know if i'm going to run into a wall. I need references to my map/tiles.
I need to know if i've collided with a ghost, so i need references to my ghost objects.
I need to know if I collided with some food and then update the scoreboard, so i need have reference to my scoreboard object.
So essentially, it feels like i'm going to be making a giant mess passing so many object references around to all my objects, that it feels like doing a "global" topobject is much cleaner.
Does anyone know how to organize this better, so that i'm doing it cleanly? Should I even be checking for collisions inside my Pacman Update(), or should I be creating seperate "PacmanObject.CheckCollisionWith()" and calling that from my Game1 Update()? Should collision logic also be seperated out into a new class?
Thanks!
Having a central point that contain reference toward your objects isn't a bad thing per se. However, a good design will put the actions that are best related to each object in the correct class. For example, your player doesn't need to have reference towards the tiles and walls. While doing an Move method, the player could call a static method in the Map class that return true/false if the next move is valid. This way, the player doesn't have any reference toward the map itself.
public class Player
{
public void Update()
{
//stuff to find nextTile position
//Call static function toward a class that contains the map data.
if (Map.TileIsWalkable(nextTile))
Move();
}
}
public class Map
{
public static Map loadedMap; // Handling it as singleton, normally you only load one map at a time.
public static bool TileIsWalkable(Vector2 position)
{
if (loadedMap == null) // Throw assert, shouldn't happen.
return //whatever test needed in loadedMap structure
}
}
You can also have a Ghost manager that keeps reference toward the ghost. The player would only need to call a method in that manager that would loop over all the ghost to see if he collides. Even better, that method could take a position and not a reference. That way, it can be reused to see if ghosts collide between each other. (random idea)
There's plenty of way to do something. The hardest in any code design is to put the stuff at the place that make the more sense and makes it the easiest to update and modify later.

Categories

Resources