Search Unity

Need help to modify existing code to make arrows stick into specific objects with tags

Discussion in 'Scripting' started by Proto-G, May 17, 2021.

  1. Proto-G

    Proto-G

    Joined:
    Nov 22, 2014
    Posts:
    213
    I currently have arrows that will hit objects with 4 different tags and cause a sound and particle effect. Currently the arrows bounds off the objects.

    I would like for the arrows to stick into the objects with tags: Flesh & Wood at whatever angle they enter the object.

    I would also like an option to destroy the arrow upon collison...
    How would I go about doing this?

    Thanks :)

    Code (CSharp):
    1. namespace VRTK.Examples.Archery
    2. {
    3.     using UnityEngine;
    4.  
    5.     public class Arrow : MonoBehaviour
    6.     {
    7.         public float maxArrowLife = 10f;
    8.         public float maxCollidedLife = 0f;
    9.         [HideInInspector]
    10.         public bool inFlight = false;
    11.  
    12.         private bool collided = false;
    13.         private Rigidbody rigidBody;
    14.         private GameObject arrowHolder;
    15.         private Vector3 originalPosition;
    16.         private Quaternion originalRotation;
    17.         private Vector3 originalScale;
    18.         private AudioSource source;
    19.  
    20.         public void SetArrowHolder(GameObject holder)
    21.         {
    22.             arrowHolder = holder;
    23.             arrowHolder.SetActive(false);
    24.         }
    25.  
    26.         public void OnNock()
    27.         {
    28.             collided = false;
    29.             inFlight = false;
    30.         }
    31.  
    32.         public void Fired()
    33.         {
    34.             if (source != null)
    35.             {
    36.                 source.Play();
    37.             }
    38.             DestroyArrow(maxArrowLife);
    39.         }
    40.  
    41.         public void ResetArrow()
    42.         {
    43.             DestroyArrow(maxCollidedLife);
    44.             collided = true;
    45.             inFlight = false;
    46.             RecreateNotch();
    47.             ResetTransform();
    48.         }
    49.  
    50.         private void Start()
    51.         {
    52.             rigidBody = GetComponent<Rigidbody>();
    53.             SetOrigns();
    54.             source = GetComponent<AudioSource>();
    55.         }
    56.  
    57.         private void SetOrigns()
    58.         {
    59.             originalPosition = transform.localPosition;
    60.             originalRotation = transform.localRotation;
    61.             originalScale = transform.localScale;
    62.         }
    63.  
    64.         private void FixedUpdate()
    65.         {
    66.             if (!collided)
    67.             {
    68.                 transform.LookAt(transform.position + rigidBody.velocity);
    69.             }
    70.         }
    71.  
    72.         private void OnCollisionEnter(Collision collison)
    73.         {
    74.             if (inFlight && isActiveAndEnabled && gameObject.activeInHierarchy)
    75.             {
    76.                 ResetArrow();
    77.             }
    78.         }
    79.  
    80.         private void RecreateNotch()
    81.         {
    82.             //swap the arrow holder to be the parent again
    83.             arrowHolder.transform.SetParent(null);
    84.             arrowHolder.SetActive(true);
    85.  
    86.             //make the arrow a child of the holder again
    87.             transform.SetParent(arrowHolder.transform);
    88.  
    89.             //reset the state of the rigidbodies and colliders
    90.             GetComponent<Rigidbody>().isKinematic = true;
    91.             GetComponent<Collider>().enabled = false;
    92.             arrowHolder.GetComponent<Rigidbody>().isKinematic = false;
    93.         }
    94.  
    95.         private void ResetTransform()
    96.         {
    97.             arrowHolder.transform.position = transform.position;
    98.             arrowHolder.transform.rotation = transform.rotation;
    99.             transform.localPosition = originalPosition;
    100.             transform.localRotation = originalRotation;
    101.             transform.localScale = originalScale;
    102.         }
    103.  
    104.         private void DestroyArrow(float time)
    105.         {
    106.             Destroy(arrowHolder, time);
    107.             Destroy(gameObject, time);
    108.         }
    109.  
    110.     }
    111.  
    112. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Hit_Damage : MonoBehaviour
    6. {
    7.     public AudioSource source;
    8.  
    9.     public GameObject fleshParticle;
    10.     public AudioClip[] fleshSound;
    11.  
    12.     public GameObject metalParticle;
    13.     public AudioClip[] metalSound;
    14.  
    15.     public GameObject stoneParticle;
    16.     public AudioClip[] stoneSound;
    17.  
    18.     public GameObject woodParticle;
    19.     public AudioClip[] woodSound;
    20.  
    21.     public float delayTime = 2;
    22.  
    23.       void OnCollisionEnter (Collision coll) {
    24.           if (coll.collider.CompareTag ("Flesh")) {
    25.               Flesh ();
    26.           }
    27.  
    28.           else if (coll.collider.CompareTag ("Metal")) {
    29.               Metal ();
    30.           }
    31.  
    32.           else if (coll.collider.CompareTag ("Stone")) {
    33.               Stone ();
    34.           }
    35.  
    36.           else if (coll.collider.CompareTag ("Wood")) {
    37.               Wood ();
    38.           }
    39.       }
    40.  
    41.       void Flesh () {
    42.           GameObject hitflesh = Instantiate(fleshParticle, transform.position, Quaternion.identity);
    43.           hitflesh.GetComponent<ParticleSystem>().Play();
    44.           source.clip = fleshSound[Random.Range(0, fleshSound.Length)];
    45.           source.Play();
    46.           Destroy (hitflesh, delayTime);
    47.       }
    48.  
    49.       void Metal () {
    50.           GameObject hitmetal = Instantiate(metalParticle, transform.position, Quaternion.identity);
    51.           hitmetal.GetComponent<ParticleSystem>().Play();
    52.           source.clip = metalSound[Random.Range(0, metalSound.Length)];
    53.           source.Play();
    54.           Destroy (hitmetal, delayTime);
    55.       }
    56.  
    57.       void Stone () {
    58.           GameObject hitstone = Instantiate(stoneParticle, transform.position, Quaternion.identity);
    59.           hitstone.GetComponent<ParticleSystem>().Play();
    60.           source.clip = stoneSound[Random.Range(0, stoneSound.Length)];
    61.           source.Play();
    62.           Destroy (hitstone, delayTime);
    63.       }
    64.  
    65.       void Wood () {
    66.           GameObject hitwood = Instantiate(woodParticle, transform.position, Quaternion.identity);
    67.           hitwood.GetComponent<ParticleSystem>().Play();
    68.           source.clip = woodSound[Random.Range(0, woodSound.Length)];
    69.           source.Play();
    70.           Destroy (hitwood, delayTime);
    71.       }
    72. }
    73.  
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    Parent it to whatever object you hit perhaps?
     
  3. Proto-G

    Proto-G

    Joined:
    Nov 22, 2014
    Posts:
    213
    Yeah, I've researched and figured out that it's best to create to child of whatever object is hit and place the arrow as the child of that child based on scale issues, but I'm not sure how go about scripting it. That's what I need assistance with. ;)
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    Ah, gotcha.

    Well, from that Collision argument passed in, you can obviously get the collider involved, as you are doing to check its tag for what it is.

    Have you tried just doing the naive:

    Code (csharp):
    1. // parent us to what we just hit so we "stick into" it
    2. transform.SetParent( coll.collider.transform);
    I suspect that might be all you need, at least for the first pass.

    You might need to adjust depth to look right, if the arrows move really fast.

    To adjust the depth you can get the point of the contact (from the Collision's contact list) and drive it in a certain distance in the opposite direction of the .normal associated with that contact, basically hard-moving it to a sufficiently-sunken position.

    As for destroying it, you could decide that based on what type of thing you hit (maybe metal stone destroy the arrow, flesh and wood let it wedge in?).
     
    Proto-G likes this.
  5. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,925