Destroying Instantiated Clone Components Breaks Original Game Object Components? - c#

Maybe im missing something obvious but to keep it short. I have working code for a character. When you "dash" I want to leave behind an after-image type effect, by cloning the player, removing its unneeded components and then applying a shader. Issue is as soon as I instantiate the clone the original player stops functioning (cant move etc). It still has all its components and everything as normal, and the clone does get the correct components removed. But it still breaks. As soon as I remove that line, its back to normal. Any ideas?
This is the only relevant code in the script that instantiates the clone.
private void DodgeEffect()
{
GameObject _DodgeSFX = Instantiate(gameObject, transform.position, transform.rotation );
Destroy(_DodgeSFX.GetComponent<PlayerController>());
Destroy(_DodgeSFX.GetComponent<PlayerCombat>());
Destroy(_DodgeSFX.GetComponent<WarpController>());
Destroy(_DodgeSFX.GetComponent<Animator>());
}

its because you are making a copy of gameObject. while Instantiate() returns a GameObject, it also returns whatever you put into the first section of the method. instead, make a seperate gameObject than the player in the editor, and make _DodgeSFX public so you can put the copy into the slot. Then, just instantiate that seperate GameObject and you wont have to destroy the components through script(because you remove the components in the editor), saving time

Ok so from some testing I think its down to the Unity.InputSystem only allowing 1 instance of each Input to be enabled at once. When I instantiated a clone of the player, it still goes through the Enable/Awake functions before those components are destroyed, and since the Inputs on that clone were never disabled, that becomes the "main" one. If I set the main player's scripts with Inputs deactive and then active again, it all works as normal. Note that the script was still working on the main character just fine, it was only the inputs that was broken. Im still not sure why this is the case, if its a limitation of the input system, or intentional, cant seem to find documentation of this experience anywhere.

Related

Spawning gameobjects relative to the position, width and length of another gameobject?

I'm currently developing a game in Unity using C# and I've run into a small problem.
I need to spawn a certain gameobjects relative to the Spawnposition and length of another game object. Now I figured that bounds.size would be the best function to use in this instance. As shown bellow I declare first the variable that uses this in my start method:
public void Start()
{
GameObject PointBar = (GameObject) Resources.Load("PointBar Horizontal");
PointBarVectorLength = PointBar.GetComponent<BoxCollider2D>().bounds.size.x;
PointBarVectorConv = Camera.main.WorldToViewportPoint(new Vector2(PointBarVectorLength, 0f));
}
However, the gameobjects in question are inactive at start's call and thus I presume don't return any value for bounds.size when called.
Does anyone know how I can access the bounds.size or equivalent of an inactive gameobject or is there something else I'm missing here?
As noted in the documentation for the Collider.bounds property, bounds "will be an empty bounding box if the collider is disabled or the game object is inactive". So your assumption was pretty much right. Since the object doesn't exist in worldspace that makes sense.
I'm not sure about the most elegant solution for your use case but two options spring to mind.
Calculate the object's spawn dimensions by accessing its transform.localScale and factoring in the scale of prospective parent objects. That could get messy but you could probably also write a helper method to make it more manageable.
Instantiate the object somewhere off screen after you load it, access its Collider.bounds property to get the information you need then move it where ever you want it or store the information for later.
There may be better solutions but that's what leaps to mind for me.
I solved the issue by using GetComponent().bounds.size.x;
instead of BoxCollider. This component can get accessed when the game object is not active.

Neither null nor type check detecting destroyed object/component?

I have an issue for which I've found a workaround, but can't understand why Unity isn't working the way I expect, or what I'm doing wrong. Basically, I am referencing a renderer component of a destroyed object in a script (long after it's been destroyed), and neither null checks nor type checks let me know it's destroyed.
I have a script that's modifying the shaders on some objects temporarily so I can apply effects on to them; when the effects are done it puts the materials/shaders back the way they were.
It happened that I was swapping out a character's weapon in the same frame I began one of these effects, so the script wound up with a reference to the renderer of a destroyed object (the old weapon). Many frames later when the effect was to finish, it naturally err'd out.
I tried a type check first to see if the reference was still to a renderer -- no luck. Unity's doc says a null check should work, but it still doesn't.
if (pair.Key != null && pair.Key is Renderer renderer) { renderer.materials = pair.Value; }
I get:
MissingReferenceException: The object of type 'SkinnedMeshRenderer' 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.
activeInHierarchy likewise does not work.
Adding a DestroyImmediate to the code where I destroy the object works fine; the object isn't there by the time the effect starts, so the reference is never made. However, that only solves this one problem, and not other such cases.
Can anyone tell me how to check properly for references to destroyed objects or components, or if I'm doing something wrong in my checking? Should I be referencing the gameObject instead of the renderer component or something like that?
EDIT:
Since a commenter asked for it, here's a gist of the full code for the effect. The destruction is happening outside this, as it's totally unrelated.
https://gist.github.com/jackphelps/f507d949a84c53457f570c5009bcb6d4
SOLVED -- SORT OF?
I changed the dictionary to store the renderer's game object instead of the renderer, and as expected a simple null check worked for detecting a destroyed object. I'd love to know why it doesn't work on the renderer, and if there's a proper way to check!
The best way I could find to solve this was to store a reference to the renderer's gameObject rather than to the renderer component itself. In this case, a simple null check at the end of the script works fine, as expected.
I'm not accepting this answer because it still doesn't tell me how to check for a component's presence when the game object was removed ¯(°_o)/¯

Unity: Camera.main is failing after I switch scenes

I am having a weird issue with some of my code, and I could really use some help.
I have a script attached to a gameobject that is unique to a particular scene, so anything within Start() will only run when that scene is loaded. In this script, I am accessing Camera.main, since I use settings attached to the camera gameobject (it may sound inefficient, but it is necessary for the style of game we are creating). Anyway, if I start from that scene directly in Unity, it works just fine, but if I start from my intro scene and then load into the aforementioned scene, I get this error:
MissingReferenceException: The object of type 'Camera' 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, I can Debug.Log(Camera.main) and it gives me the name of the camera. So Camera.main is not null, and it is not destroyed like it says in the error message. Here is my full script:
private void Start()
{
Debug.LogError(Camera.main);
gameManager = FindObjectOfType<GameManagerScript>();
if (Camera.main == null)
{
Debug.LogError("Camera.main is null");
}
else
{
gameManager.LoadMusic(Camera.main);
gameManager.LoadAmbient(Camera.main);
gameManager.FadeStereoPan(Camera.main.gameObject.GetComponent<SwipeActivator>().stereoPanInNode);
}
}
The three functions above are custom functions I wrote, but I don't know why they would be causing the issue, since they work if I start up the scene directly.
I wasn't having this issue for months, and then all of a sudden, I am getting this error, even though I didn't change any of the code. Any help would be greatly appreciated.
I believe your MainCamera is being destroyed between scenes. Set it up as "DontDestroyOnLoad()"
See this Unity question:
https://answers.unity.com/questions/430141/need-the-same-main-camera-for-multiple-scenes.html
Ah, I fixed it. I dove into my custom functions and found that I was accessing a camera variable that is set at the beginning of the game, and then on each camera transition, but it was failing since I was loading a scene and no transitions that scene had yet to be completed. I just had to reassign that variable in the script above so it was not pointing to the destroyed object in the previous scene. Thank you JiveTurkey for pointing me in the right direction!

Infinite Road Update

I am working on Unity for a month. I am new on Unity and C#, before Unity I worked other game engines. Whatever I am working on infinite run game, I wrote random road generator. Road generator is working well but I have problem about updating road. I can update road manualy like this. How can I update it automaticly?
void Update()
{
if(Input.GetKeyDown(KeyCode.A)) UpdateRoad();
}
My UpdateRoad method adding road like this(I am using object pooling).
I want to update after Link Road, OnExitTrigger or something I dont know. How can I do it?
You would need to implement Object Pooling.
I would suggest making your Design of Objects first so you can test. Or if not use, the stock Blocks Primitive of Unity3D as your Prefabs. I hope you already know prefabs. It is a major key for making infinite runner. Actually a main core for making any kinds of game.
Prefabs is an Object File where you can Instantiate it in a location. So lets say you will generate a Flat walkable, then Generate a Pit. You would probably want to stack them together.
Now Generating them is easy. You would not like to go in an Update? Approach because most likely you're not going to update, but you're going to further stack what is going on ahead, based on your game logic.
To further Understand this, Unity3D already made a project or Fully Detailed tutorial. It maybe made in 2D but it is going to be the same, if you're going to change the Collider2D to Collider <- this is important in your case.
https://unity3d.com/learn/tutorials/modules/beginner/live-training-archive/infinite-runner
Update
You would need to create an Object, that is invisible. Meaning a Trigger.
Then on Trigger call your method UpdateRoad();
https://unity3d.com/learn/tutorials/modules/beginner/physics/colliders-as-triggers
Detailed Videos about Trigger.
If I understood your needs correctly, you could create Empty Object name it SpawnPoint, set position for Spawn Point as you need (out of the camera view) and then Instanciate random prefabs of road. Concerning On TriggerExit - it could be used to destroy "old piece of road". But to have it working properly, dont forget to set collider and rigitbody to your objects. Dont add collider2D or Rigitbody2d, add and use Box Collider and Rigitbody components

DontDestroyOnLoad is not Working on Scene?

I Need to apply DontDestroyOnLoad on Scene.is it possible?
I Need to Do not disturb the scene when going in to another scenes also.here i'm sending mail,when ever clicking send button its going to authentication in mail server in this time my scene idle means not responding anything until come back to the response from mail server,so on that time i show one loading bar in my scene.this is not do process.the entire scene is hang until came response from mail server,so how to solve this?
void Awake()
{
DontDestroyOnLoad(this.gameObject);
}
After reading so many non-answers I finally found the answer in a Unity forum. DontDestroyOnLoad ONLY works if the game object in question is at a "root level" meaning right under the scene, not nested under any other object. This is not mentioned anywhere in the documentation.
When loading a new level, scene, all Game Objects of the previous scene are destroyed by Unity.
If you want to protect a Game Object you can use the function.
DontDestroyOnLoad(gameObject);
It is important to note that when you say: this.gameObject you are pointing to pretty much the same thing, it just happens that this points directly to the script attached to that gameObject. So you don't need the this part, just gameObject will do.
Ideally you could protect that gameObject inside void Awake()
void Awake()
{
DontDestroyOnLoad(gameObject);
}
The above code will prevent Unity from destroying that gameObject unless your game closes completely or at a later point you call Destroy() on it. That means you can change from scene to scene and the gameObject will survive. However, if you make it back to the scene that creates that gameObject you are protecting you may run into problems if you do not have the logic implemented that prevents you from protecting a second, third, or many of that gameObject.
Your second question, if I understand it correctly:
You want to send mail when you change scenes, but your progress bar wont progress while changing scenes, it just stays there, static.
If that is the case then your problem is in Application.LoadLevel(sceneName); If you have the free version of Unity, then you need to come up with your own creative way of showing that progress bar, because Application.LoadLevel() will halt everything until it takes you to the new scene.
I don't completely understand what you are saying.
But because in your context, this in represents most probably a Monobehaviour, try the following:
void Awake() {
DontDestroyOnLoad(this.gameObject);
}
or
void Awake() {
DontDestroyOnLoad(gameObject);
}
See http://docs.unity3d.com/Documentation/ScriptReference/Object.DontDestroyOnLoad.html
I recommend you use a coroutine, with the 'yield' statement
check out this documentation of the WWW class, which likewise involves writing code to cope with waiting for a response from the web, without hanging your Unity3d program
coroutines are pretty powerful if you're working with tasks that take more than a frame or two. Richard Fine (AltDevBlog) has posted a really detailed description of what they are and how to use them, which I thoroughly recommend.

Categories