Search Unity

How to set object in game to awaken on distance from character

Discussion in '2D' started by WebMagi, May 24, 2015.

Thread Status:
Not open for further replies.
  1. WebMagi

    WebMagi

    Joined:
    May 24, 2015
    Posts:
    23
    Currently Rigidbody 2D has the setting: Start Asleep, which means the "Object is initially asleep but can be woken by collisions". Is there a way to configure an object to awaken when the character comes within a set distance?

    This is something that would need to be controlled per object.
     
  2. LiberLogic969

    LiberLogic969

    Joined:
    Jun 29, 2014
    Posts:
    138
    Why are you wanting this kind of functionality?
     
  3. WebMagi

    WebMagi

    Joined:
    May 24, 2015
    Posts:
    23
    I need physics objects to awaken when the character comes within a set distance in a scene.
     
  4. inthemilkywat

    inthemilkywat

    Joined:
    Dec 29, 2013
    Posts:
    56
    You can use Vector2.Distance(transform.position,target.position).
     
  5. WebMagi

    WebMagi

    Joined:
    May 24, 2015
    Posts:
    23
    Thanks @inthemilkywat. My apologies for the dim-witted questions, but does your solution awaken an object which has been set with the Rigidbody 2D component to Start Asleep? Is there a way to achieve this within the Inspector panel using a different component?

    I may very well end up with a thousand or more objects in the course of the game that I will need to awaken at various distances from the character. Many objects can be duplicated, so the same distance can be used in those cases, but I expect that there will be a hundred or more objects (enemies, platforms, etc.) that will need unique distance settings.

    I am trying to determine if Unity is the right game engine for the simple game I am working on. I've built a prototype scene in Construct 2, and the desired results were achieved (somewhat) by using their Line of Sight behavior. But my best results came from prototyping in Buildbox, where believe it or not, Wake Up can be distance based or collision based, and the Wake Up distance can be set as low as 0.001. No crazy event system like in Construct 2, just simple controls and values in a visual panel that activates when selecting an object. Stupid simple right?

    I've watched every one of the Unity 2D training videos here: http://unity3d.com/learn/tutorials/modules/beginner/2d/2d-overview, and I think the 2D workflows in Unity are superior to every game engine I've tested so far. I love it. I want to use it for this and all future games. But I'm a designer with limited experience in coding C# and complex mathematical expressions. I have 16 years experience as a freelance web designer and front-end developer, and I'm a hardcore software junkie. I've mastered dozens of applications from Photoshop, After Effects, to Ableton Live, Toon Boom Animate.... I've set my sights next on Unity for expanding my services into game creation. Hopefully this issue is just a temporary hiccup, but it's blocking me from prototyping even the first scene.

    The ideal solution for me, obviously, would be a "Distance-Based" setting in the Rigidbody 2D component to waken an object at the required distance. Aside from that, if I somehow manage to intuit the development of a script that could be used in place of this missing feature, could it be written in such a way that duplicating an object does not force me to create a new script each time for the new object's name?

    Can Unity's Event System or Event Trigger components achieve the desired results? If so, are there examples or documentation showing how it could be setup?
     
  6. inthemilkywat

    inthemilkywat

    Joined:
    Dec 29, 2013
    Posts:
    56
    No there is no option to check distance between two objects in the rigidbody2D component. You would have to write a script that checks if a character is in a certain distance to this object in the update method. Then just attach the script to your object. I assume you are going to be instantiating a bunch of these objects so just make sure the prefab has this script on it.

    Code (CSharp):
    1. // Update is called once per frame
    2.     void Update () {
    3.         if (Vector2.Distance (transform.position, character.transform.position) < 5) {
    4.             Debug.Log ("Distance is less than 5");
    5.             // do something here
    6.         }
    7.     }
     
    theANMATOR2b likes this.
  7. WebMagi

    WebMagi

    Joined:
    May 24, 2015
    Posts:
    23
    Thanks, I really appreciate that you would take the time to write out your script. I'm not seeing how this script awakens an object though, whose Rigidbody 2D Sleeping Mode has been set to Start Asleep. I don't need it to transform its position as much as I need it to awaken. The purpose of having the object to Start Asleep is so that it's physics is disabled. When the character comes within a specified distance, I need the object to awaken, which would then activate its physics. That's all I need the object to do, awaken and be itself - according to its various component settings.

    I think your script is an excellent start. And although I may have to create a hundred or more instances of it for the various objects whose distances will be unique to a scene, at least I have something to test.
     
  8. inthemilkywat

    inthemilkywat

    Joined:
    Dec 29, 2013
    Posts:
    56
    All you need to do is call the Rigidbody2D component on this game object and use the WakeUp() method.

    Code (CSharp):
    1. private GameObject player;
    2. private float distance = 5f;
    3.  
    4. // Use this for initialization
    5.     void Start () {
    6.         player = GameObject.FindGameObjectWithTag ("Player");
    7.     }
    8.  
    9. // Update is called once per frame
    10.     void Update () {
    11.         if (Vector2.Distance (transform.position, player.transform.position) < distance) {
    12.             GetComponent<Rigidbody2D>().WakeUp();
    13.         }
    14.     }
     
  9. WebMagi

    WebMagi

    Joined:
    May 24, 2015
    Posts:
    23
    This is what I ended up with:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class AwakeOnDistance : MonoBehaviour
    5. {
    6.     [SerializeField] private Transform target;            // The target objects wake up to
    7.     private GameObject player;
    8.     [SerializeField] private float distance = 100f;       // Setting distance to target in the Inspector panel
    9.     [SerializeField] private bool go_Sleep = false;       // Is the object going back to sleep?
    10.     [SerializeField] private float sleep_Distance = 0f;   // Distance until object sleeps.
    11.  
    12.   // Use this for initialization
    13.     void Start () {
    14.     player = GameObject.FindGameObjectWithTag ("Player");
    15. }
    16.  
    17.   // Update is called once per frame
    18.     void Update () {
    19.     if (Vector2.Distance (transform.position, player.transform.position) < distance) {
    20.         GetComponent<Rigidbody2D>().WakeUp();
    21. }
    22.    
    23. }
    24. }
    Which resulted in the script having controls in the Inspector panel:


    The Target & Distance both work perfectly.
    The "go_Sleep" & "sleep_Distance" fields do not actually work at this time. It's just something I'm working towards.

    There was at least one instance in the scenes I prototyped in Buildbox were I needed an object to go back to sleep at a specific distance from its start position. It would be great if I could get this nailed down too. Can anyone point me to examples of how this might be coded?

    Thanks.
     
  10. inthemilkywat

    inthemilkywat

    Joined:
    Dec 29, 2013
    Posts:
    56
    To find the start position of the object you would have to initialize it in the start() function. Then reference that when finding the distance between its current and starting position. It's basically the same code as before but now you want to use the Sleep() method.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class AwakeOnDistance : MonoBehaviour
    5. {
    6.     private Vector2 startPosition;
    7.     private float distance = 5f;
    8.  
    9.     // Use this for initialization
    10.     void Start () {
    11.         startPosition = transform.position;
    12.     }
    13.  
    14.     // Update is called once per frame
    15.     void Update () {
    16.         if (Vector2.Distance (startPosition, transform.position) >= distance) {
    17.             GetComponent<Rigidbody2D>().Sleep();
    18.         }  
    19.     }
    20. }
     
  11. WebMagi

    WebMagi

    Joined:
    May 24, 2015
    Posts:
    23
    Nice! I really appreciate your help on this. Hopefully the 2D team will see its importance and add wake and sleep on distance to the appropriate component soon. I'm running into other issues related to this that the script isn't handling. Such as the fact that some objects I need to awaken have to be close enough together to appear as one whole unit, which would then disperse one at a time in quick succession as the player moves past. The problem is that being so close together, they awaken automatically in unison before the player even moves. I tried adding "Is Kinematic", but that froze them completely. So I added "GetComponent<Rigidbody2D>().isKinematic = false;" under the wake up method to counter, and it seems to be working so far.

    Then there's the Enemy script, which doesn't seem to contain a setting for actually destroying the player. For all the good that Unity has for 2D, there are simple things that are either missing, or overly complicated to setup.

    But with your help, I am a little bit closer to getting down to some actual scene building. Which reminds me, Unity can play scenes back-to-back right? See here for what I mean: https://www.scirra.com/forum/how-do-i-configure-scenes-to-play-back-to-back_t145496
     
  12. jprocha101

    jprocha101

    Joined:
    Apr 8, 2015
    Posts:
    134
  13. jwarner0915

    jwarner0915

    Joined:
    Jan 17, 2016
    Posts:
    3
    This is an old thread, but the way games used to do this.. i.e... The old school method, was to create an invisible object that the user collided with and then when that collide even happened it would "wake" or invoke the methods on the target object. Space Quest and Kings Quest and all those old school games did this. So the main character would walk over or collide with a certain spot and boom the camera in the room would see you or something ominous would happen.
    - J
     
  14. codefish83

    codefish83

    Joined:
    Mar 4, 2015
    Posts:
    1
  15. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,497
    Please don't necro threads like this (it's from 2015!) but especially with incorrect information. The above is a 3D physics query, completely inappropriate for a solution to a 2D problem.
     
Thread Status:
Not open for further replies.