2017-08-26 58 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