Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

My Line Renderer can't shoot upwards?

Discussion in 'Scripting' started by Jeepster, Sep 10, 2018.

  1. Jeepster

    Jeepster

    Joined:
    Jan 23, 2014
    Posts:
    401
    Hi, I followed a tutorial to get my player to shoot in multiplayer using Photon. It works, but for some reason my player can shoot every which way but upwards. When I point anywhere above my player and shoot, the line that gets rendered heads from my players gun directly to coordinates 0,0,0. I can't figure out why, I hope someone can help. Here's my shooting script:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PlayerShooting : Photon.MonoBehaviour {
    6.    
    7.     float cooldown = 0;
    8.    
    9.     FXManager fxManager;
    10.     WeaponData weaponData;
    11.     public Camera cam;
    12.  
    13.     void Start()
    14.     {
    15.         fxManager = GameObject.FindObjectOfType<FXManager>();
    16.  
    17.         if (fxManager == null)   {
    18.             Debug.LogError("Couldn't find FXManager script");
    19.         }
    20.  
    21.  
    22.     }
    23.     // Update is called once per frame
    24.     void Update () {
    25.  
    26.         cooldown -= Time.deltaTime;
    27.  
    28.         if(Input.GetButton("Fire1"))
    29.         {//Player wants to shoot so SHOOT!
    30.             Fire();
    31.  
    32.         }
    33.     }
    34.     [PunRPC]
    35.     void Fire()
    36.     {
    37.         //fxManager = GameObject.FindObjectOfType<FXManager>();
    38.         if (weaponData == null)
    39.         {
    40.             weaponData = gameObject.GetComponentInChildren<WeaponData>();
    41.             if (weaponData == null)
    42.             {
    43.                 Debug.LogError("Did not find a WeaponData script on child object");
    44.             }
    45.             return;
    46.         }
    47.         if (cooldown > 0)
    48.         {
    49.             return;
    50.         }
    51.         //Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward );
    52.         Ray ray = new Ray(cam.transform.position, cam.transform.forward);
    53.         Transform hitTransform;
    54.         Vector3 hitPoint;
    55.         //if (Physics.Raycast(ray, out hitInfo))
    56.         //{
    57.         //    Debug.Log("We hit: " + hitInfo.collider.name);
    58.         //}
    59.  
    60.         hitTransform = FindClosestHitObject(ray, out hitPoint);
    61.         if (hitTransform != null)
    62.         {
    63.             Debug.Log("We hit: " + hitTransform.name);
    64.  
    65.             // we could do a FX animation on the hit location
    66.             // DoSmokeEffect (hitInfo.point);
    67.  
    68.             Health h = hitTransform.GetComponent<Health>();
    69.             while (h == null && hitTransform.parent)
    70.             {
    71.                 hitTransform = hitTransform.parent;
    72.                 h = hitTransform.GetComponent<Health>();
    73.             }
    74.  
    75.  
    76.  
    77.             if (h != null)
    78.             {
    79.                 //h.TakeDamage(damage);
    80.  
    81.  
    82.                 //The RPC (remote calls a function) and shares it with the network. In this case "All" players in the game get the updated parameter: damage  - from the health script. (It updates health when and object is hit on everybodys computer)
    83.                 //h.GetComponent<PhotonView>().RPC("TakeDamage", PhotonTargets.All, damage);
    84.  
    85.                 PhotonView pv = h.GetComponent<PhotonView>();
    86.                 if (pv == null)
    87.                 {
    88.                     Debug.LogError("Missing PhotonView script");
    89.                 }
    90.                 else
    91.                 {
    92.                     h.GetComponent<PhotonView>().RPC("TakeDamage", PhotonTargets.AllBuffered, weaponData.damage);
    93.                 }
    94.  
    95.             }
    96.             if(fxManager != null)
    97.             {
    98.                 DoGunFX(hitPoint);
    99.             }
    100.         }
    101.         else
    102.             {
    103.                 //We didn't hit anything except empty space, but let's do an FX anyway.
    104.                 if (fxManager != null)
    105.                 {
    106.                     DoGunFX(hitPoint);
    107.                     hitPoint = cam.transform.position + (cam.transform.forward *100f);
    108.                 }
    109.             }
    110.  
    111.        
    112.         cooldown = weaponData.fireRate;
    113.  
    114.     }
    115.  
    116.  
    117.     void DoGunFX(Vector3 hitPoint)
    118.     {
    119.  
    120.         WeaponData weaponData = gameObject.GetComponentInChildren<WeaponData>();
    121.  
    122.         fxManager.GetComponent<PhotonView>().RPC("SniperBulletFX", PhotonTargets.All, weaponData.transform.position, hitPoint);
    123.     }
    124.  
    125.     Transform FindClosestHitObject(Ray ray, out Vector3 hitpoint)
    126.     {
    127.         RaycastHit[] hits = Physics.RaycastAll(ray);
    128.  
    129.         Transform closestHit = null;
    130.         float distance = 0f;
    131.         hitpoint = Vector3.zero;
    132.  
    133.         foreach (RaycastHit hit in hits)
    134.         {
    135.             if(hit.transform != this.transform && (closestHit == null || hit.distance < distance))
    136.             {
    137.                 //we have hit something that is not us:
    138.                 //a: not us
    139.                 //b: the first thing we hit that isn't us
    140.                 closestHit = hit.transform;
    141.                 distance = hit.distance;
    142.                 hitpoint = hit.point;
    143.             }
    144.     }
    145.         //closest hit is now either null,or the closest thing that isn't us.
    146.         return closestHit;
    147.     }
    148. }
    149.  
    And here's the line renderer script called FXManager:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class FXManager : Photon.MonoBehaviour {
    6.  
    7.  
    8.     public GameObject SniperBulletFXPrefab;
    9.  
    10.  
    11.     [PunRPC]
    12.     void SniperBulletFX(Vector3 startPos, Vector3 endPos)
    13.     {
    14.         Debug.Log("SniperBulletFX");
    15.         GameObject sniperFX = (GameObject)Instantiate(SniperBulletFXPrefab, startPos, Quaternion.LookRotation(endPos - startPos));
    16.         LineRenderer lr = sniperFX.transform.Find("LineFX").GetComponent<LineRenderer>();
    17.         lr.SetPosition(0, startPos);
    18.         lr.SetPosition(1, endPos);
    19.  
    20.     }
    21. }
     
  2. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    Quaternion.LookRotation requires an up direction to denote which direction is up relative to the forward vector. The default of just world space up will work in all cases except when forward is also world space up.
    https://docs.unity3d.com/ScriptReference/Quaternion.LookRotation.html

    Imagine having to define the complete rotation of the bullet when both forward and up are world space up. It is clear that the bullet should be directed straight up, but it is unclear how the bullet should be rotated around its forward axis. It's the classic look at problem, which generally doesn't work for straight up or down. LookRotation does supply the solution by offering to enter the local up vector too.
     
    Jeepster likes this.
  3. Jeepster

    Jeepster

    Joined:
    Jan 23, 2014
    Posts:
    401
    Very well explained. Thanks jvo3dc. I'll see if I can fix it in my code :)
     
  4. Jeepster

    Jeepster

    Joined:
    Jan 23, 2014
    Posts:
    401

    Ok, so I understand the theory, but I just can't get it to work with my code.

    Do I add the Vector3.up to the (endPos - startPos) parenthesis in the line instantiator line?
    Code (CSharp):
    1.         GameObject sniperFX = (GameObject)Instantiate(SniperBulletFXPrefab, startPos, Quaternion.LookRotation(endPos - startPos));
    2.  
    The example in the API doesn't include specific start and end positions, which is what is throwing me off...
     
  5. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    Well, that is the whole issue here. There is not simple way to define the rotation based on a start and end position. It gets unstable when the positions are above each other. Common issue with any look at.

    The best solution would be to directly pass the rotation Quaternion of the transform:
    Code (csharp):
    1.  
    2. fxManager.GetComponent<PhotonView>().RPC("SniperBulletFX", PhotonTargets.All, weaponData.transform.position, hitPoint, weaponData.transform.rotation);
    3.  
    4. [PunRPC]
    5. void SniperBulletFX(Vector3 startPos, Vector3 endPos, Quaternion rotation)
    6. {
    7.    Debug.Log("SniperBulletFX");
    8.    GameObject sniperFX = (GameObject)Instantiate(SniperBulletFXPrefab, startPos, rotation);
    9.    LineRenderer lr = sniperFX.transform.Find("LineFX").GetComponent<LineRenderer>();
    10.    lr.SetPosition(0, startPos);
    11.    lr.SetPosition(1, endPos);
    12. }
    13.  
     
  6. Jeepster

    Jeepster

    Joined:
    Jan 23, 2014
    Posts:
    401
    Okay. The strange thing is that the original code I posted worked in the guys tutorial I followed, but it's an old tutorial with an older version of unity, perhaps that's why.

    But I tried your code and it doesn't work. I'm assuming : fxManager.GetComponent<PhotonView>().RPC("SniperBulletFX", PhotonTargets.All, weaponData.transform.position, hitPoint, weaponData.transform.rotation);

    -should be in the PlayerShooting script, in the DoGunFX function? I really appreciate your help
     
  7. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    In which way does it not work? (Doesn't compile -> which message, does something other then intended -> what does it do.)
     
  8. Jeepster

    Jeepster

    Joined:
    Jan 23, 2014
    Posts:
    401
    There's no error message, it simply does the exact same thing as the original code. When I point upwards and shoot, the line renderer goes from gun to coordinates 0,0,0. if I point straight forward or anywhere below it shoots as it should.
     
  9. Jeepster

    Jeepster

    Joined:
    Jan 23, 2014
    Posts:
    401
    Does
    If you have any other suggestions I would really appreciate it my friend :) I guess I could ditch the line renderer and only have the muzzle flash but that would be kind of a shame.