Search Unity

[Solved] If collision, move newly spawned units by width of unit to a direction until no collisions.

Discussion in 'Scripting' started by asperatology, May 27, 2015.

  1. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    This is a unit I have. It's just a representation.



    This is a picture of what the title meant:



    Explanation:

    1. This is one of many typical scenario in which a unit is about to spawn at the red Player Spawn location.
    2. The green, newly-spawned unit has spawned. It detects that there's a collision, therefore it moves to the right. Note that it can be in any direction, it's just that "right" is more natural.
    3. The green unit continues to detect collisions. Note that black units are already spawned into the game. Collision detection therefore determines that the green unit must continue to move right.
    4. This repeats Step 3.
    5. This repeats Step 3.
    6. Finally, the green unit detects no collision. All the rest of the black units stay put in their original positions.
    7. The green unit is now spawned in, therefore it changes to black.

    And here's my current, unfinished code:

    Code (CSharp):
    1.     public void OnCollisionEnter(Collision collision) {
    2.         [deprecated] collision.other
    3.  
    4.         if (this.SpawnedObjectList.Contains(this.gameObject)) {
    5.             return;
    6.         }
    7.         else {
    8.             bool collidesWithOthers = true;
    9.             while (collidesWithOthers) {
    10.              
    11.             }
    12.             this.SpawnedObjectList.Add(this.gameObject);
    13.         }
    14.     }
    Since "collision.other" is now deprecated in Unity 5, I thought of trying to get the "other collided game objects", but I have no clue so far as to how to obtain the other game objects when collision occurs.

    I haven't wrote down codes to move the newly-spawned unit across in one direction, because I also haven't figured out how to obtain the width of the game object, as well as where the collision occurs.

    This tutorial video isn't helping much to retrieve the "collided" object.

    I would say a lot has changed, so I would like to ask for help on this.
    • Where can I obtain "other" of type GameObject when a collision occurs?
    • How can I get the width of a GameObject (size)?
    • How can I get the position/location of where the collision occurs?
     
    Last edited: May 27, 2015
  2. hamsterbytedev

    hamsterbytedev

    Joined:
    Dec 9, 2014
    Posts:
    353
    • Where can I obtain "other" of type GameObject when a collision occurs?
    Collision.gameObject
    • How can I get the width of a GameObject (size)?
    Collision.collider.bounds.size <--this will give you a vector 3 detailing the size in all directions of the collider. Width is usually x, but could be y, or z depending on the orientation in space that you are calling width.
    • How can I get the position/location of where the collision occurs?
    Collision.contacts[0] <-- this will return the first point where the Collider objects made contact.

    That should get you on the right track. Best of luck and let me know if this works out for you!
     
  3. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    New question, and this is something I really need help with:

    Two same game object with colliders, how do you move the instantiated game object to a vacant location that is not blocked by the older game object?

    Context:

    When the green unit spawns in where one of the black unit is at, both the green and black units calls on OnTriggerEnter(). However, the green unit never calls on OnCollisionEnter() and OnTriggerEnter(). The green unit has the following collision handling code below as a component. By theory, when the green unit is instantiated in a place where the black unit is already occupying, the green unit's collider should call on either OnTriggerEnter() or OnCollisionEnter(), which should in turn, move the green unit away from the occupied space by 1.1f Unity unit.

    Or maybe my coroutine is written incorrectly...

    This is what I am doing for collision handling and spawning below.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class CollisionHandling : MonoBehaviour {
    5.     public bool hasCollided;
    6.     public Vector3 spawnLocation;
    7.  
    8.     public void Update() {
    9.         if (this.hasCollided) {
    10.             Vector3 pos = this.transform.position;
    11.             pos.x += 1.1f;
    12.             pos.y = 0.58f;
    13.             this.transform.position = pos;
    14.             this.hasCollided = false;
    15.             Debug.Log("Moved to position: " + pos.ToString());
    16.         }
    17.     }
    18.  
    19.     public void OnTriggerEnter(Collider other) {
    20.         this.hasCollided = true;
    21.     }
    22.  
    23.     public void OnTriggerExit(Collider other) {
    24.         this.hasCollided = false;
    25.     }
    26.  
    27.     public void OnTriggerStay(Collider other) {
    28.         this.hasCollided = true;
    29.     }
    30.  
    31.     public void OnTriggerExit(UnityEngine.Collision collision) {
    32.         this.hasCollided = false;
    33.     }
    34.  
    35.     public void OnTriggerEnter(UnityEngine.Collision collision) {
    36.         this.hasCollided = true;
    37.     }
    38.  
    39.     public void OnTriggerStay(UnityEngine.Collision collision) {
    40.         this.hasCollided = true;
    41.     }
    42.  
    43.     public void ResetSpawnLocation() {
    44.         this.spawnLocation = Vector3.zero;
    45.     }
    46.  
    47.     public void Start() {
    48.         this.spawnLocation = new Vector3();
    49.     }
    50. }
    51.  
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class ConstantSpawn : MonoBehaviour {
    6.     public GameObject SpawnLocation;
    7.     public GameObject SpawnedPrefab;
    8.     public CollisionHandling CollisionHandling;
    9.  
    10.     private int SpawnCounter = 0;
    11.     private float StartTime = 0.0f;
    12.  
    13.     void Start() {
    14.         GameObject gameObject = (GameObject) Resources.Load("Prefabs/Temporary Unit");
    15.         CollisionHandling = gameObject.GetComponent<CollisionHandling>();
    16.     }
    17.  
    18.     // Update is called once per frame
    19.     void Update() {
    20.         if (Network.isClient || Network.isServer) {
    21.             if (Time.time - StartTime >= 5f) {
    22.                 StartTime = Time.time;
    23.  
    24.                 this.StartCoroutine(CR_SpawnTempUnit());
    25.             }
    26.         }
    27.     }
    28.  
    29.     public IEnumerator CR_SpawnTempUnit() {
    30.         GameObject spawnedObject = (GameObject)Network.Instantiate(Resources.Load("Prefabs/Temporary Unit"), CollisionHandling.spawnLocation, Quaternion.identity, UnitManager.PG_Player);
    31.         spawnedObject.name = spawnedObject.name + " " + string.Format("{0}", this.SpawnCounter);
    32.         this.SpawnCounter++;
    33.         yield return new WaitForEndOfFrame();
    34.  
    35.         CollisionHandling handling = spawnedObject.GetComponent<CollisionHandling>();
    36.         while (handling.hasCollided) {
    37.             yield return new WaitForEndOfFrame();
    38.         }
    39.  
    40.         Network.Instantiate(Resources.Load("Prefabs/Player"), spawnedObject.transform.position, Quaternion.identity, UnitManager.PG_Player);
    41.         Destroy(spawnedObject);
    42.     }
    43.  
    44.  
    45.     public void OnCollisionEnter(UnityEngine.Collision col) {
    46.         Debug.Log("OnCollisionEnter: " + col.gameObject.ToString());
    47.     }
    48. }
    49.  
     
  4. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    I think I fixed it. Apparently, thanks to Munchy2007 for his help, I was able to get it working without requiring an additional script and game object.

    Here's the code for making the diagram in the first post to work:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class ConstantSpawn : MonoBehaviour {
    6.     public GameObject SpawnLocation;
    7.     public GameObject SpawnedPrefab;
    8.  
    9.     private int SpawnCounter = 0;
    10.     private float StartTime = 0.0f;
    11.  
    12.     void Start() {
    13.         GameObject gameObject = (GameObject) Resources.Load("Prefabs/Temporary Unit");
    14.     }
    15.  
    16.     // Update is called once per frame
    17.     void Update() {
    18.         if (Network.isClient || Network.isServer) {
    19.             if (Time.time - StartTime >= 5f) {
    20.                 StartTime = Time.time;
    21.  
    22.                 this.StartCoroutine(CR_SpawnTempUnit());
    23.             }
    24.         }
    25.     }
    26.  
    27.     public IEnumerator CR_SpawnTempUnit() {
    28.         Vector3 spawnLocation = Vector3.zero;
    29.         bool tryAgain = true;
    30.         while (tryAgain) {
    31.             tryAgain = false;
    32.             Collider[] colliders = Physics.OverlapSphere(spawnLocation, 0.6f);
    33.             foreach (Collider c in colliders) {
    34.                 if (c.gameObject.name.Equals("Floor")) {
    35.                     continue;
    36.                 }
    37.                 if (c.gameObject.tag.Equals("TemporaryUnit") || c.gameObject.tag.Equals("Player") || c.gameObject.name.Equals("EntityBody")) {
    38.                     tryAgain = true;
    39.                     break;
    40.                 }
    41.             }
    42.             if (tryAgain) {
    43.                 spawnLocation.x += 1.05f;
    44.             }
    45.         }
    46.  
    47.         GameObject spawnedObject = (GameObject)Network.Instantiate(Resources.Load("Prefabs/Player"), spawnLocation, Quaternion.identity, UnitManager.PG_Player);
    48.         spawnedObject.name = spawnedObject.name + " " + string.Format("{0}", this.SpawnCounter);
    49.         this.SpawnCounter++;
    50.         yield return null;
    51.     }
    52.  
    53.  
    54.     public void OnCollisionEnter(UnityEngine.Collision col) {
    55.         Debug.Log("OnCollisionEnter: " + col.gameObject.ToString());
    56.     }
    57. }
    58.  
     
    hamsterbytedev likes this.
  5. hamsterbytedev

    hamsterbytedev

    Joined:
    Dec 9, 2014
    Posts:
    353