Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Arczer · Mar 21, 2013 at 01:13 AM · c#errorenemies

Enemies Cannot Be Selected After The First One Dies...

Hello,

I am trying to fix a problem I have, when I have an enemy selected and it dies, which means that it is destroyed, then I cannot select the next enemy...

This is the error I get -


 MissingReferenceException: The object of type 'GameObject' 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.
 PlayerAttack.Attack () (at Assets/Resources/Script/PlayerAttack.cs:30)
 PlayerAttack.Update () (at Assets/Resources/Script/PlayerAttack.cs:23)


&


 MissingReferenceException: The object of type 'Transform' 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.
 UnityEngine.Transform.get_position () (at C:/BuildAgent/work/7535de4ca26c26ac/Runtime/ExportGenerated/Editor/UnityEngineTransform.cs:26)
 Targetting.<SortTargetsByDistance>m__0 (UnityEngine.Transform t1, UnityEngine.Transform t2) (at Assets/Resources/Script/Targetting.cs:35)
 System.Array.qsort[Transform] (UnityEngine.Transform[] array, Int32 low0, Int32 high0, System.Comparison`1 comparison) (at /Applications/buildAgent/work/b59ae78cff80e584/mcs/class/corlib/System/Array.cs:1772)
 System.Array.Sort[Transform] (UnityEngine.Transform[] array, Int32 length, System.Comparison`1 comparison) (at /Applications/buildAgent/work/b59ae78cff80e584/mcs/class/corlib/System/Array.cs:1699)
 Rethrow as InvalidOperationException: Comparison threw an exception.
 System.Array.Sort[Transform] (UnityEngine.Transform[] array, Int32 length, System.Comparison`1 comparison) (at /Applications/buildAgent/work/b59ae78cff80e584/mcs/class/corlib/System/Array.cs:1702)
 System.Collections.Generic.List`1[UnityEngine.Transform].Sort (System.Comparison`1 comparison) (at /Applications/buildAgent/work/b59ae78cff80e584/mcs/class/corlib/System.Collections.Generic/List.cs:579)
 Targetting.SortTargetsByDistance () (at Assets/Resources/Script/Targetting.cs:34)
 Targetting.TargetEnemy () (at Assets/Resources/Script/Targetting.cs:42)
 Targetting.Update () (at Assets/Resources/Script/Targetting.cs:90)


And here is the code -


 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public class Targetting : MonoBehaviour {
     public List<Transform> targets;
     public Transform selectedTarget;
     
     private Transform myTransform;
 
     void Start () {
         targets = new List <Transform>();
         selectedTarget = null;
         myTransform = transform;
         
         AddAllEnemies();
     }
     
     public void AddAllEnemies()
     {
         GameObject[] go = GameObject.FindGameObjectsWithTag("Enemy");
         
         foreach(GameObject enemy in go)
             AddTarget(enemy.transform);
     }
     
     public void AddTarget(Transform enemy)
     {
         targets.Add(enemy);
     }
     
     private void SortTargetsByDistance()
     {
         targets.Sort(delegate(Transform t1, Transform t2){
                     return (Vector3.Distance(t1.position, myTransform.position)).CompareTo(Vector3.Distance(t2.position, myTransform.position));
                     });
     }
     private void TargetEnemy()
     {
         if(selectedTarget == null)
         {
             SortTargetsByDistance();
             selectedTarget = targets[0];
         }
         else
         {
             int index = targets.IndexOf(selectedTarget);
             
             if(index < targets.Count - 1)
             {
                 index++;
             }
             else
             {
                 index = 0;
             }
             
             DeselectTarget();
             selectedTarget = targets[index];
         }
         
         SelectTarget();
         
     }
     
     private void SelectTarget()
     {
         selectedTarget.renderer.material.color = Color.red;
         
         selectedTarget.GetComponent<EnemyDeath>().Selected = true;
         
         PlayerAttack pa = (PlayerAttack)GetComponent("PlayerAttack");
         
         pa.target = selectedTarget.gameObject;
     }
     
     private void DeselectTarget()
     {
         selectedTarget.renderer.material.color = Color.white;
         
         selectedTarget.GetComponent<EnemyDeath>().Selected = false;
         
         selectedTarget = null;
     }
     
     void Update () {
         
         if(Input.GetKeyDown(KeyCode.Mouse1))
         {
             TargetEnemy();
         }    
     }
 }


I am new to programming, although I am learning, so any help with this would be great.

Thank you

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by whebert · Mar 21, 2013 at 03:05 AM

If your Enemy game objects are being destroyed somewhere other than the above script, you will run into this issue. What is happening is that your targets list contains all the Transforms of the Enemies in your scene at startup, but when one of those Enemies gets destroyed, your target list still contains a reference to the no longer existing GameObject's Transform. And you try to access the destroyed Transform's position when you sort the list, which causes havoc.

There are probably several ways to avoid this, depending on what you wish to accomplish (code samples untested).

  1. Don't destroy your Enemy GameObjects. Perhaps just de-activate them and make them invisible? And when you target it, you could check if it is active and skip it if so...

  2. Let the above Targeting.cs script manage when an Enemy is destroyed in the scene. When that needs to happen, you can remove the Transform from your targets list with targets.Remove(enemyToBeDestroyed.transform); This way, you keep a clean targets list and won't have the above issue.

  3. If you don't want Targeting.cs to manage when to destroy an Enemy, you could have an Enemy "de-register" itself with the Targeting script. On the Enemy's OnDestroy() method, you could do something like: Targetting targeting = FindObjectOfType(typeof(Targetting)) as Targetting; if(targeting != null) targeting.RemoveTransform(gameObject.transform); And of course add a method to Targetting, public void RemoveTransform(Transform transform) { targets.Remove(transform);

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Arczer · Mar 21, 2013 at 04:14 AM 0
Share

Thanks for the reply :)

I have followed the 1st suggestion and it works, when the enemy is destroyed it is deactivated and invisible, however now I am having difficulty finding a way to skip the disabled enemy from being targeted...

avatar image whebert · Mar 21, 2013 at 12:59 PM 0
Share

I haven't tested this code, but something like the following should work in your TargetEnemey() method.

In Unity 3.x

 int index = targets.IndexOf(selectedTarget);
         
 do
 {
    if(++index >= targets.Count)
    {
       index = 0;
    }
 }while(targets[index].gameObject.active == false);

In Unity 4

 int index = targets.IndexOf(selectedTarget);
         
 do
 {
    if(++index >= targets.Count)
    {
       index = 0;
    }
 }while(targets[index].gameObject.activeInHierarchy == false);

This assumes you have some method of knowing when you are out of Enemies and won't try to target the next one if there are no longer any available, otherwise the above code would just cycle infinitely.

avatar image Arczer · Mar 21, 2013 at 04:00 PM 0
Share

That works :)

Thank you for all the help!

avatar image whebert · Mar 21, 2013 at 04:39 PM 0
Share

Awesome, glad it worked. Feel free to mark the answer correct if ya like. :D

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

11 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Multiple Cars not working 1 Answer

rts developement 0 Answers

OnDestroy() : Some objects were not cleaned up when closing the scene 1 Answer

Error NullReferenceException: Object reference not set to an instance of an object 1 Answer

Getting ArgumentOutOfRangeException on array c# 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges