Unity | MissingReferenceException on scene reload - unity3d

So I have a simple local multiplayer game using the new input system. There's the game scene and the results scene. Once the game ends, the results scene is loaded and you can press "start" to restart the game (load the game scene again).
The problem is, after I reload the game scene and then trigger an InputAction (seems to be only on context.started):
MissingReferenceException while executing 'PlayerInput.onActionTriggered' callbacks
MissingReferenceException: The object of type 'Rigidbody2D' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
The weird thing is, none of these supposedly missing references are actually missing. The players still move using the "missing" rigidbody and etc.
I apologize if I don't explain well. I'm new to Unity and quite lost. I'm happy to share screenshots or snippits of my code I honestly just don't know where to look for this.

You should make null all action events in start

Term
This is a common problem for developers using Unity. This is a problem that occurs so often that Unity Techonology has already given it a term to explain it.
'Fake Null'
unity blog link
https://blog.unity.com/technology/custom-operator-should-we-keep-it
In short, this happens because Unity's Object is a wrapper class that indicate pointer.
Code of Conduct
You can understand the details by reading the article on the Unity blog.
Unity developers need to be careful when using C#'s nullable syntax. (?, ??...etc)
Example Code
public class MyClass : Monobehaviour
{
[SerializeField] private Rigidbody _rigidbody;
private void DoSomething()
{
// This can cause Runtime error especially when GameObject that has
// Rigidbody already been Destroyed.
_rigidbody?.CallSomeMethod();
// This is Defensive Code preventing Runtime error
if (_rigidbody != null)
{
_rigidbody.CallSomeMethod();
}
}
}

Related

Loading a scene in Unity twice causes some game objects to lose some components

When I hit play the game scene behaves as normal, even if I come from a different scene.
But when I am on the game scene and go to other scene and back again to the game scene some components from some game objects.
I am using SceneManager.LoadScene("SceneName"); to move around scenes, and every component was added in the editor and saved in the scene.
And as an example here is the Game Manager inspector at first load of game scene:
And second load of game scene:
Windows Controls is a script much like the others missing.
Am I doing something wrong?
Thanks in advance.
Without knowing what's going on inside the GameManager and the FoodManager scripts, I think you use the DontDestroyOnLoad similar what is showed on the bottom of the page, and your code destroys the scripts.
Simply put, I was short-sighted, I used a singleton pattern to access the managers and the way I did, at least, doesn't work in this context.
Any manager that I needed access I created a static instance, but since I checked for its existence elsewhere, the second time the component was destroyed.
public GameManager Instance {get; private set;}
void Awake()
{
if(Instance is not Null && Instance != this)
{
Destroy(Instance);
return;
}
Instance = this;
}
I realize that every time the scene loads the components are new objects, but I am still to understand why there is still copies of the old components.
I fixed it by using the [SerializeField] on any manager reference that I could and and manually adding them on the inspector, for some game objects that were instantiated at run time I pass the manager in a method.
GameManager gameManager;
public void Manager(GameManager _gameManager)
{
gameManager = _gameMananger;
}
GameObject gameObject = Instantiate(prefab);
gameObject.GetComponent<Script>().Manager(this);

Unity MRTK with HoloLens 2: How to detect whether a hand touches a GameObject in code?

I have been working with Unity 2020.3 LTS, the Windows XR Plugin, and the amazing MRTK 2.7.0 to port an existing application to HoloLens 2.
In this application I have a scene with several GameObjects in it and I need to detect whether a hand touches a GameObject (either with the indexfingertip near interaction or the pinch gesture far interaction). The important part here is that this detection needs to happen in a central script in the scene (i.e. maybe have the hand as an object in the code) and not from the view of the touched Gameobject itself.
I have successfully implemented the latter using this example with the two code examples below on that page, but the touched GameObject itself firing events via a listener does not work well with my use case. I need to detect the touch from the hand's perspective, so to speak.
I have searched the web and the Microsoft MRTK documentation several times for this and unfortunately I could not find anything remotely helpful. For head-gaze the documentation has a super simple code example that works beautifully: Head-gaze in Unity. I need the exact same thing for detecting when a hand touches a GameObject.
Eventually I will also need the same thing for eye-tracking when looking at a GameObject, but I have not looked into this yet and right now the hand interaction is giving me headaches. I hope someone can help me with this. Thanks in advance :).
but the touched GameObject itself firing events via a listener does not work well with my use case.
Why does the event not work? Could you provide more detail about it?
In addition to NearInteractionTouchable, have you tried the Interactable component? It's usually used to attach to the touched Game Object and will fire the event receiver when catching input actions. In the event receiver (in the Component UI), you can add any function attached to any object as the listener, such as a central script in the scene. It should be an effortless way can meet your request. For more information please see: Event
After some additional fiddling around I was able to get it to work the way I want/need to with the Touch Code Example. The solution was to create an empty GameObject variable in the code of the central script that is continuously checked whether it is null or not. The touch on the GameObject itself then binds itself to that checked GameObject variable as long as it is touched and sets it back to null once it is not touched anymore. This allows the central script to work with the touched GameObject as long as it is touched.
void Start()
{
centralScript = GameObject.Find("Scripts").GetComponent<CentralScript>();
NearInteractionTouchableVolume touchable = gameObject.AddComponent<NearInteractionTouchableVolume>();
touchable.EventsToReceive = TouchableEventType.Pointer;
pointerHandler = gameObject.AddComponent<PointerHandler>();
pointerHandler.OnPointerDown.AddListener((e) =>
{
centralScript.handTouchGameObject = gameObject;
});
pointerHandler.OnPointerUp.AddListener((e) =>
{
centralScript.handTouchGameObject = null;
});
}

Unity 5.3+ Networking Load Next Level

In a networked game project following on from the Unity Multiplayer Tutorial, how is one supposed to go about changing scene to a new level/map while preserving camera/player GO/health etc. in one overarching master scene. (e.g. Gameplay.unity with Level1.unity or Level2.unity added to it)
All related help seems to be legacy code, singleplayer solutions or a more specialized circumstance. The current Unity 5.5 documentation suggests ServerChangeScene - which only seems to provide half the solution.
Does something like ServerAddScene and ServerGetScene exist?
Attempted solutions have been using DontDestroyOnLoad on known GameObjects in the master scene and keep a currentMapNumber variable synced between client NetworkManagers that gets updated when a player reaches the end-of-level trigger. This is then checked in the Update() method and either calls
networkManager.ServerChangeScene("Level" + networkManager.GetComponent<NetGame>().mapNumber);
or
SceneManager.LoadScene("Level" + networkManager.GetComponent<NetGame>().mapNumber, LoadSceneMode.Additive);
neither of which work as expected.
I am able to do this through an additive scene loading i used this code.
[ClientRpc]
public void RpcLoadLevelAcrossNetwork() {
SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
}
ClientRpc will load the new scene to all connected clients and additive scene loading will allow you to preserve camera/player GO/health etc

Unity, to what object should I attach my game engine script

Me and my friend are building a simple idle game as our first project in unity.
We got to the point at which we build a script that handles all calculations, and communicates with each GameObject the player sees.
Now, to what should we attach this script?
We would rather not use a GameObject because:
1) The GameObject would be an overkill
2) The GameObject lies in the space where all of my "physical" objects exist (That would be useless since the script does not have to "exist somewhere")
First time posting in stackoverflow, if I made any mistake please tell me ^^
Convention says to put it on the main camera or an empty GameObject.
If you really don't want to do either of those, you could make your class static.
If your class inherits from MonoBehaviour you have to attach it to a GameObject. If you want to attach it to a GameObject it has to inherit from MonoBehaviour.
If you want to better understand the Unity way, I advise you to read up on Entity-Component Systems:
GameObject are Entities
MonoBehaviour are Components
Services and managers generally get implemented as Components in Unity which then get attach to the main camera or to empty GameObjects named after them.
You can create a usual singleton class, and "Game Initializer" monobehaviour, that will initialize all your singletone managers, fabrics, etc...
Just add this monobehaviour to every scene in empty gameobject with a code like that:
if(GameManager.instance == null)
new GameManager();
Or in case of scriptableObjects,
if(GameManager.instance == null)
gameManager.init()
Also, a good desicion is to use Entity System pattern, here is frameworks for unity (Unity-Ash, Entitas, etc)

Player dies when hitting the floor

I am trying to make a game in unity, and I am new to unity and coding, and I have started making a game, I have made some progress on it but I am having trouble finding some of my answers on youtube and the unity forum, and sometimes when I do, I still can't get things to work. So this is what I'm trying to do.
I have a map and the player is on top of the tower, I want the player to fall and when hitting the ground, dies with it displaying game over, What could I do to make this happen and what script?
So i have this now,
// Ground.cs: Kills players that touch this.collider.
using UnityEngine;
// Attach this to the grass collider
public class Ground : MonoBehaviour {
// Called when another collider hits the grass.
// This is part of Unity!
void OnCollisionEnter(Collision c) {
// Does the other collider have the tag "Player"?
if (c.gameObject.tag == "Player") {
// Yes it does. Destroy the entire gameObject.
Destroy(c.gameObject);
}
}
}
Now, I need to it transition to a game over overlay, which asks me to restart, yes or no.
The resources are out there in regards to learning Unity3D efficiently.
Look at the Unity3D tutorials: https://unity3d.com/learn/tutorials
These tutorials are usually kept up to date in terms of not using deprecated code. Additionally, several of the tutorials will teach you how to set up events like those that you need.
In regards to your immediate question though, look into forming the logic for your game.
You're going to need allow your player gameobject to fall via either gravitational force enacted on a rigidbody or hard-coded physics being applied to the gameobject. Next you will need to determine if the player gameobject has collided with the "floor". If so you will need to trigger an event to destroy the player gameobject, then display a GUI Text that says Game Over.
Look around more at tutorials and get better acquianted with Unity. Over time, you'll learn how to make things happen. If you have more questions, feel free to ask.
Answer to you update:
If your code is functioning correctly and your destroying your gameobject correctly, then awesome! You're learning fast!
The next step could be:
Create a Canvas, create a gui panel, create a gui text
That gui text object can have your Game Over Text
Now, create a button that you will utilize as the restart button
You can have the button call a function which utilizes SceneManager.LoadScene to reload the scene. Look here for an example: http://answers.unity3d.com/questions/1109497/unity-53-how-to-load-current-level.html
Next, Disable the panel as you will not need it until your player dies.
When your player collides with the ground you will destroy the player gameobject and set the panel you created to active. (you can trigger these actions via a listener in code or via the button component in the inspector).