2017-08-26 60 views
1

我正在嘗試將Unity生存射手遊戲部署到android設備。除了當我射擊敵人時,遊戲工作得很好,它不會受到任何傷害,也不會死亡。 這是我的PlayerShooting腳本。統一生存射手敵人無損傷 - Android

using UnityEngine; 
using System.Threading; 
using UnityStandardAssets.CrossPlatformInput; 

namespace CompleteProject 
{ 
public class PlayerShooting : MonoBehaviour 
{ 
    public int damagePerShot = 20;     // The damage inflicted by each bullet. 
    public float timeBetweenBullets = 0.15f;  // The time between each shot. 
    public float range = 100f;      // The distance the gun can fire. 


    float timer;         // A timer to determine when to fire. 
    Ray shootRay;         // A ray from the gun end forwards. 
    RaycastHit shootHit;       // A raycast hit to get information about what was hit. 
    int shootableMask;        // A layer mask so the raycast only hits things on the shootable layer. 
    ParticleSystem gunParticles;     // Reference to the particle system. 
    LineRenderer gunLine;       // Reference to the line renderer. 
    AudioSource gunAudio;       // Reference to the audio source. 
    Light gunLight;         // Reference to the light component. 
    public Light faceLight;        // Duh 
    float effectsDisplayTime = 0.2f;    // The proportion of the timeBetweenBullets that the effects will display for. 
    public float timertime = 0.0f; 


    void Awake() 
    { 
     // Create a layer mask for the Shootable layer. 
     shootableMask = LayerMask.GetMask ("Shootable"); 

     // Set up the references. 
     gunParticles = GetComponent<ParticleSystem>(); 
     gunLine = GetComponent <LineRenderer>(); 
     gunAudio = GetComponent<AudioSource>(); 
     gunLight = GetComponent<Light>(); 
     //faceLight = GetComponentInChildren<Light>(); 
    } 


    void Update() 
    { 
     // Add the time since Update was last called to the timer. 
     timer += Time.deltaTime; 

    #if !MOBILE_INPUT 
     // If the Fire1 button is being press and it's time to fire... 
     if(Input.GetButton ("Fire1") && timer >= timeBetweenBullets && Time.timeScale != 0) 
     { 
      // ... shoot the gun. 
      Shoot(); 
     } 
     #else 
     // If there is input on the shoot direction stick and it's time to fire. 
     bool check = CrossPlatformInputManager.GetButtonDown("JumpButton"); 
     check = true; 
     //Debug.Log(check); 
     if(check == true) 
     // if ((CrossPlatformInputManager.GetAxisRaw("Move X") != 0 || CrossPlatformInputManager.GetAxisRaw("Move Y") != 0) && timer >= timeBetweenBullets) 
     { 
      // ... shoot the gun 
      //System.Threading.Thread.Sleep(2000); 
      timertime -= Time.deltaTime; 
      if(timertime < 0.0f) 
      { 
       Shoot(); 
       timertime = 0.175f; 
      } 
     } 
     #endif 
     // If the timer has exceeded the proportion of timeBetweenBullets that the effects should be displayed for... 
     if(timer >= timeBetweenBullets * effectsDisplayTime) 
     { 
      // ... disable the effects. 
      DisableEffects(); 
     } 
    } 


    public void DisableEffects() 
    { 
     // Disable the line renderer and the light. 
     gunLine.enabled = false; 
     faceLight.enabled = false; 
     gunLight.enabled = false; 
    } 


    public void Shoot() 
    { 
     // Reset the timer. 
     Debug.Log("Inside Shoot"); 
     timer = 0f; 

     // Play the gun shot audioclip. 
     gunAudio.Play(); 

     // Enable the lights. 
     gunLight.enabled = true; 
     faceLight.enabled = true; 

     // Stop the particles from playing if they were, then start the particles. 
     gunParticles.Stop(); 
     gunParticles.Play(); 

     // Enable the line renderer and set it's first position to be the end of the gun. 
     gunLine.enabled = true; 
     gunLine.SetPosition (0, transform.position); 

     // Set the shootRay so that it starts at the end of the gun and points forward from the barrel. 
     shootRay.origin = transform.position; 
     shootRay.direction = transform.forward; 

     // Perform the raycast against gameobjects on the shootable layer and if it hits something... 
     Debug.Log("Going inside Physics Raycast"); 
     if(Physics.Raycast (shootRay, out shootHit, range, shootableMask)) 
     { 
      // Try and find an EnemyHealth script on the gameobject hit. 
      Debug.Log("Inside Physics Raycast"); 
      EnemyHealth enemyHealth = shootHit.collider.GetComponent <EnemyHealth>(); 
      Debug.Log (enemyHealth); 
      Debug.Log ("Checking if enemyHealth is not null"); 

      // If the EnemyHealth component exist... 
      if(enemyHealth != null) 
      { 
       // ... the enemy should take damage. 
       Debug.Log("Inside enemyHealth != null if condition"); 
       enemyHealth.TakeDamage (damagePerShot, shootHit.point); 
      } 

      // Set the second position of the line renderer to the point the raycast hit. 
      gunLine.SetPosition (1, shootHit.point); 
     } 
     // If the raycast didn't hit anything on the shootable layer... 
     else 
     { 
      // ... set the second position of the line renderer to the fullest extent of the gun's range. 
      gunLine.SetPosition (1, shootRay.origin + shootRay.direction * range); 
     } 
    } 
} 
} 

這裏是我的EnemyHealth腳本。

using UnityEngine; 
using UnityStandardAssets.CrossPlatformInput; 

namespace CompleteProject 
{ 
public class EnemyHealth : MonoBehaviour 
{ 
    public int startingHealth = 100;   // The amount of health the enemy starts the game with. 
    public int currentHealth;     // The current health the enemy has. 
    public float sinkSpeed = 2.5f;    // The speed at which the enemy sinks through the floor when dead. 
    public int scoreValue = 10;     // The amount added to the player's score when the enemy dies. 
    public AudioClip deathClip;     // The sound to play when the enemy dies. 


    Animator anim;        // Reference to the animator. 
    AudioSource enemyAudio;      // Reference to the audio source. 
    ParticleSystem hitParticles;    // Reference to the particle system that plays when the enemy is damaged. 
    CapsuleCollider capsuleCollider;   // Reference to the capsule collider. 
    bool isDead;        // Whether the enemy is dead. 
    bool isSinking;        // Whether the enemy has started sinking through the floor. 


    void Awake() 
    { 
     // Setting up the references. 
     anim = GetComponent <Animator>(); 
     enemyAudio = GetComponent <AudioSource>(); 
     hitParticles = GetComponentInChildren <ParticleSystem>(); 
     capsuleCollider = GetComponent <CapsuleCollider>(); 

     // Setting the current health when the enemy first spawns. 
     currentHealth = startingHealth; 
    } 


    void Update() 
    { 
     // If the enemy should be sinking... 
     if(isSinking) 
     { 
      // ... move the enemy down by the sinkSpeed per second. 
      transform.Translate (-Vector3.up * sinkSpeed * Time.deltaTime); 
     } 
    } 


    public void TakeDamage (int amount, Vector3 hitPoint) 
    { 
     // If the enemy is dead... 
     if(isDead) 
      // ... no need to take damage so exit the function. 
      return; 

     // Play the hurt sound effect. 
     enemyAudio.Play(); 

     // Reduce the current health by the amount of damage sustained. 
     currentHealth -= amount; 

     // Set the position of the particle system to where the hit was sustained. 
     hitParticles.transform.position = hitPoint; 

     // And play the particles. 
     hitParticles.Play(); 

     // If the current health is less than or equal to zero... 
     if(currentHealth <= 0) 
     { 
      // ... the enemy is dead. 
      Death(); 
     } 
    } 


    void Death() 
    { 
     // The enemy is dead. 
     isDead = true; 

     // Turn the collider into a trigger so shots can pass through it. 
     capsuleCollider.isTrigger = true; 

     // Tell the animator that the enemy is dead. 
     anim.SetTrigger ("Dead"); 

     // Change the audio clip of the audio source to the death clip and play it (this will stop the hurt clip playing). 
     enemyAudio.clip = deathClip; 
     enemyAudio.Play(); 
    } 


    public void StartSinking() 
    { 
     // Find and disable the Nav Mesh Agent. 
     GetComponent <UnityEngine.AI.NavMeshAgent>().enabled = false; 

     // Find the rigidbody component and make it kinematic (since we use Translate to sink the enemy). 
     GetComponent <Rigidbody>().isKinematic = true; 

     // The enemy should no sink. 
     isSinking = true; 

     // Increase the score by the enemy's score value. 
     ScoreManager.score += scoreValue; 

     // After 2 seconds destory the enemy. 
     Destroy (gameObject, 2f); 
    } 
} 
} 

我已經把日誌無處不在,發現從PlayerShooting腳本enemyHealth對象總是返回空,即使如果我打子彈的敵人。

PlayerShooting script Screenshot

Unity Screenshot

需要知道爲什麼它總是返回null,如何使它比其他的空當我擊中敵人。

+0

做'的debug.log(shootableMask)'告訴我什麼該值 – Programmer

+0

值是512。@Programmer – Rohit

+0

你嘗試我離開了答案? – Programmer

回答

2

您已經在使用Layer來確保raycast僅在shootableMask圖層上擊中GameObjects,這是「可拍攝」圖層,因此圖層問題已消除。

剩下的唯一可能的問題是EnemyHealth腳本沒有附加到GameObject或者一些GameObjects。

瀏覽所有GameObjects和預製件,選擇「可拍攝」層上的每一個,然後確保EnemyHealth腳本附加到它們。如果EnemyHealth腳本附加到每個腳本,則GetComponent <EnemyHealth>()不應該爲null

1

,則應該更換Getcomponent<>功能分爲FindObjectOfType因爲Getcomponent只能從遊戲對象獲取的成分,在這種情況下,EnemyHealth腳本不會在同一個對象與PlayerShooting存在,所以你不能得到的組件。 Read more about FindObjectOfType

+0

不是一個好主意,因爲OP想要對raycast命中的特定對象造成傷害,而不僅僅是一些隨機的GameObject。 Getcomponent在這種情況下是正確的。 – Programmer