Search Unity

Special case of 3D moving platform: walking NPC and multi-directional, rotating platform

Discussion in 'Physics' started by andyastro, Sep 18, 2015.

  1. andyastro

    andyastro

    Joined:
    Sep 17, 2015
    Posts:
    16
    Dear community, I come to add up to the pile of questions about handling moving platforms. Nevertheless, at least in my defense I feel that my question brings some new flavors and complexity that might be of interest to others.

    My 3D game has some very big platforms that move both vertically and horizontally, as well as sometimes rotate a bit (somewhat similar to the Pirate Ship ride present in real life parks). I need NPCs to walk over these platforms when platforms are moving in these many ways, as well as the main player, of course. Maybe it is worth mentioning that mine is not a FPS game: movement more-or-less resembles that of RTS, since the main character follows mouse clicks (so, if it helps, I can use solutions that disable gravity of objects, since it is not crucial to my application).

    Of course, I have found the very many questions about moving platforms. Some have shed light to my problem, but in general none was able to fully solve my issues. I set the platforms to be parent of the NPC objects, and these I set as Kinematic. When not in movement, the NPCs follow the platform suitably: up, down, to any side, even rotate together. However, when they move at the same time as these platforms, problems begin to arise. It is almost as if NPCs got detached, since their movement do not follow the platform and they end up out of it. When NPCs are moving and platform rotates, the scenario is even worse: NPCs' meshes are crazily.

    Here you have a small example of code I've been trying in order to test the mechanics:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class NewBehaviourScript : MonoBehaviour {
    5.    
    6.     public GameObject person; //this represents either the NPC or the main player
    7.     public GameObject floor; //this represents the platform
    8.     private Vector3 target;
    9.     private bool walking = false;
    10.     private Vector3 temp;
    11.     private Renderer floor_rend;
    12.     private Vector3 floor_center;
    13.    
    14.     // Use this for initialization
    15.     void Start () {
    16.        
    17.     }
    18.    
    19.     // Update is called once per frame
    20.     void Update () {
    21.        
    22.         if(Input.GetMouseButtonDown(0)){
    23.             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    24.             RaycastHit hit;
    25.            
    26.             if(Physics.Raycast(ray, out hit)){
    27.                 Debug.DrawLine (ray.origin, hit.point);
    28.             }
    29.             target = new Vector3(hit.point.x, hit.point.y, hit.point.z);
    30.            
    31.             //store the difference between point hit by ray and the centroid of the platform mesh
    32.             floor_center = floor.GetComponent<Renderer>().bounds.center;
    33.             temp= target - floor_center;
    34.            
    35.             walking = true;
    36.            
    37.              
    38.         }
    39.  
    40.         //making NPC move
    41.         if(c1+floor_center != person.transform.position && walking){
    42.             person.transform.LookAt(c1+floor_center);
    43.             person.transform.Translate(Vector3.forward * Time.deltaTime*2);
    44.             if(c1+floor_center == person.transform.position){walking = false;}
    45.         }
    46.  
    47.  
    48.        //Input keys to make the platform move
    49.         if(Input.GetKey("a")) floor.transform.Translate(Vector3.back*Time.deltaTime);
    50.         if(Input.GetKey("d")) floor.transform.Translate(Vector3.forward*Time.deltaTime);
    51.         if(Input.GetKey("w")) floor.transform.Translate(Vector3.up*Time.deltaTime);
    52.         if(Input.GetKey("s")) floor.transform.Translate(Vector3.down*Time.deltaTime);
    53.         if(Input.GetKey("e")) floor.transform.Rotate(Mathf.Lerp(0, 45, Time.deltaTime), 0, 0);
    54.         if(Input.GetKey("q")) floor.transform.Rotate(Mathf.Lerp(0, -45, Time.deltaTime), 0, 0);
    55.     }
    56. }
    57.  
    Any ideas will be very much appreciated.
     
  2. MattGen

    MattGen

    Joined:
    May 12, 2015
    Posts:
    63
    I think you should find a solution that does not require you the parenting step.
    I'm not familiar with NPC in Unity at all, but I have this idea : can't you have a NavMesh on your platforms, and tell your NPC not to go over a certain distance from the center of the platform (I guess you're already doing that, right ?) ?
     
  3. andyastro

    andyastro

    Joined:
    Sep 17, 2015
    Posts:
    16
    Hi MattGen, thanks for dropping by. So, why do you think I shouldn't resort to a solution that requires parenting? With parenting, I at least get the NPCs correctly attached to the platform when they are stopped... which is something I did not have until parenting and Kinematic-ing them.

    I also did not understand why do you think I should avoid going over a certain distance from the center of the platform. What my code above was doing is different. For a given NPC/playerchar that will move around the platform, it tries to store the destination point (in World space) in relation to the center of the platform, so when the platform moves, the code supposedly updates the destination point in World space in relation to where the center of the platform is at the moment. In theory, that should work, but is not working. I my self wondered if using a NavMesh would be better in this case, but seems like them I would have to mess with the physics when the platform rotates.
     
  4. MattGen

    MattGen

    Joined:
    May 12, 2015
    Posts:
    63
    Hi ! I guess you know that better than me. I stated this about parenting 'cause I often have transforms issues with child objects.