I am trying to deploy the Unity Survival Shooter game to the android device. The game works just fine except when I shoot the enemy, it doesn't take any damage and don't die.
Here is my PlayerShooting script.
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);
}
}
}
}
And here is my EnemyHealth script.
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);
}
}
}
I have put the log everywhere and found that the enemyHealth object from PlayerShooting script is always returning Null even though if I hit the enemy with bullets.
Need to know why it is always returning Null and how do I make it other than Null when I hit the enemy.
You are already using Layer to make sure that the raycast hit just the GameObjects on the shootableMask layer which is the "Shootable" layer so layer issue problem is eliminated.
The only possible problem left is that the EnemyHealth script is not attached to the GameObject or maybe some of the GameObjects.
Go through all your GameObjects and prefabs, select each one on the "Shootable" layer then make sure that the EnemyHealth script is attached to them. The GetComponent <EnemyHealth>() should never be null if the EnemyHealth script is attached to each one.
You should change the Getcomponent<> function into FindObjectOfType because Getcomponent only gets the component from that game object, in this situation the EnemyHealth Script doesn't exist in same object with PlayerShooting so you cant get the component. Read more about FindObjectOfType
Related
I'm new to Unity and C#, trying to make a 2D game.
The animator controller screenshot with all the transition is attached, the (isGrounded) bool from idle to jump is false, from jump to idle is true, and from run to jump is false, but in this case, the character doesn't jump, it shakes in its place transitioning from idle to jump very quickly. When I remove the jump animation the character moves normally but of course no jumping. What could be the problem here?
This is also the CharacterController2D script:
public float jumpForce = 600f;
// player health
public int playerHealth = 1;
// LayerMask to determine what is considered ground for the player
public LayerMask whatIsGround;
internal void EnemyBounce(CharacterController2D characterController2D)
{
throw new NotImplementedException();
}
// Transform just below feet for checking if player is grounded
public Transform groundCheck;
// player can move?
// we want this public so other scripts can access it but we don't want to show in editor as it might confuse designer
[HideInInspector]
public bool playerCanMove = true;
// SFXs
public AudioClip coinSFX;
public AudioClip deathSFX;
public AudioClip fallSFX;
public AudioClip jumpSFX;
public AudioClip victorySFX;
// private variables below
// store references to components on the gameObject
Transform _transform;
Rigidbody2D _rigidbody;
Animator _animator;
AudioSource _audio;
// hold player motion in this timestep
float _vx;
float _vy;
// player tracking
bool _facingRight = true;
bool _isGrounded = false;
bool _isRunning = false;
bool _canDoubleJump = false;
// store the layer the player is on (setup in Awake)
int _playerLayer;
// number of layer that Platforms are on (setup in Awake)
int _platformLayer;
void Awake()
{
// get a reference to the components we are going to be changing and store a reference for efficiency purposes
_transform = GetComponent<Transform>();
_rigidbody = GetComponent<Rigidbody2D>();
if (_rigidbody == null) // if Rigidbody is missing
Debug.LogError("Rigidbody2D component missing from this gameobject");
_animator = GetComponent<Animator>();
if (_animator == null) // if Animator is missing
Debug.LogError("Animator component missing from this gameobject");
_audio = GetComponent<AudioSource>();
if (_audio == null)
{ // if AudioSource is missing
Debug.LogWarning("AudioSource component missing from this gameobject. Adding one.");
// let's just add the AudioSource component dynamically
_audio = gameObject.AddComponent<AudioSource>();
}
// determine the player's specified layer
_playerLayer = this.gameObject.layer;
// determine the platform's specified layer
_platformLayer = LayerMask.NameToLayer("Platform");
}
// this is where most of the player controller magic happens each game event loop
void Update()
{
// exit update if player cannot move or game is paused
if (!playerCanMove || (Time.timeScale == 0f))
return;
// determine horizontal velocity change based on the horizontal input
_vx = CrossPlatformInputManager.GetAxisRaw("Horizontal");
// Determine if running based on the horizontal movement
if (_vx != 0)
{
_isRunning = true;
}
else
{
_isRunning = false;
}
// set the running animation state
_animator.SetBool("Running", _isRunning);
// get the current vertical velocity from the rigidbody component
_vy = _rigidbody.velocity.y;
// Check to see if character is grounded by raycasting from the middle of the player
// down to the groundCheck position and see if collected with gameobjects on the
// whatIsGround layer
_isGrounded = Physics2D.Linecast(_transform.position, groundCheck.position, whatIsGround);
// allow double jump after grounded
if (_isGrounded)
{
_canDoubleJump = true;
}
// Set the grounded animation states
_animator.SetBool("Grounded", _isGrounded);
if (_isGrounded && CrossPlatformInputManager.GetButtonDown("Jump")) // If grounded AND jump button pressed, then allow the player to jump
{
DoJump();
}
else if (_canDoubleJump && CrossPlatformInputManager.GetButtonDown("Jump")) // If candoublejump and jump button pressed, then allow player to double jump
{
DoJump();
// disable double hump after double jumping since you can only really do it once
_canDoubleJump = false;
}
// If the player stops jumping mid jump and player is not yet falling
// then set the vertical velocity to 0 (he will start to fall from gravity)
if (CrossPlatformInputManager.GetButtonUp("Jump") && _vy > 0f)
{
_vy = 0f;
}
// Change the actual velocity on the rigidbody
_rigidbody.velocity = new Vector2(_vx * moveSpeed, _vy);
// if moving up then don't collide with platform layer
// this allows the player to jump up through things on the platform layer
// NOTE: requires the platforms to be on a layer named "Platform"
Physics2D.IgnoreLayerCollision(_playerLayer, _platformLayer, (_vy > 0.0f));
}
// Checking to see if the sprite should be flipped
// this is done in LateUpdate since the Animator may override the localScale
// this code will flip the player even if the animator is controlling scale
void LateUpdate()
{
// get the current scale
Vector3 localScale = _transform.localScale;
if (_vx > 0) // moving right so face right
{
_facingRight = true;
}
else if (_vx < 0)
{ // moving left so face left
_facingRight = false;
}
// check to see if scale x is right for the player
// if not, multiple by -1 which is an easy way to flip a sprite
if (((_facingRight) && (localScale.x < 0)) || ((!_facingRight) && (localScale.x > 0)))
{
localScale.x *= -1;
}
// update the scale
_transform.localScale = localScale;
}
// if the player collides with a MovingPlatform, then make it a child of that platform
// so it will go for a ride on the MovingPlatform
void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag == "MovingPlatform")
{
this.transform.parent = other.transform;
}
}
// if the player exits a collision with a moving platform, then unchild it
void OnCollisionExit2D(Collision2D other)
{
if (other.gameObject.tag == "MovingPlatform")
{
this.transform.parent = null;
}
}
//make the player jump
void DoJump()
{
// reset current vertical motion to 0 prior to jump
_vy = 0f;
// add a force in the up direction
_rigidbody.AddForce(new Vector2(4, jumpForce));
// play the jump sound
PlaySound(jumpSFX);
}
// do what needs to be done to freeze the player
void FreezeMotion()
{
playerCanMove = false;
_rigidbody.velocity = new Vector2(0, 0);
_rigidbody.isKinematic = true;
}
// do what needs to be done to unfreeze the player
void UnFreezeMotion()
{
playerCanMove = true;
_rigidbody.isKinematic = false;
}
// play sound through the audiosource on the gameobject
void PlaySound(AudioClip clip)
{
_audio.PlayOneShot(clip);
}
// public function to apply damage to the player
public void ApplyDamage(int damage)
{
if (playerCanMove)
{
playerHealth -= damage;
if (playerHealth <= 0)
{ // player is now dead, so start dying
PlaySound(deathSFX);
StartCoroutine(KillPlayer());
}
}
}
// public function to kill the player when they have a fall death
public void FallDeath()
{
if (playerCanMove)
{
playerHealth = 0;
PlaySound(fallSFX);
StartCoroutine(KillPlayer());
}
}
// coroutine to kill the player
IEnumerator KillPlayer()
{
if (playerCanMove)
{
// freeze the player
FreezeMotion();
// play the death animation
_animator.SetTrigger("Death");
// After waiting tell the GameManager to reset the game
yield return new WaitForSeconds(2.0f);
if (GameManager.gm) // if the gameManager is available, tell it to reset the game
GameManager.gm.ResetGame();
else // otherwise, just reload the current level
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
public void CollectCoin(int amount)
{
PlaySound(coinSFX);
if (GameManager.gm) // add the points through the game manager, if it is available
GameManager.gm.AddPoints(amount);
}
// public function on victory over the level
public void Victory()
{
PlaySound(victorySFX);
FreezeMotion();
_animator.SetTrigger("Victory");
if (GameManager.gm) // do the game manager level compete stuff, if it is available
GameManager.gm.LevelCompete();
}
// public function to respawn the player at the appropriate location
public void Respawn(Vector3 spawnloc)
{
UnFreezeMotion();
playerHealth = 1;
_transform.parent = null;
_transform.position = spawnloc;
_animator.SetTrigger("Respawn");
}
public void EnemyBounce()
{
DoJump();
}
}
I also tried adding a separate Jump script, it doesn't work.
Just gonna take some notes while reading the code...
This:
// Determine if running based on the horizontal movement
if (_vx != 0)
{
_isRunning = true;
}
else
{
_isRunning = false;
}
// set the running animation state
_animator.SetBool("Running", _isRunning);
Can be replaced by
_isRunning = _vx != 0;
_animator.SetBool("Running", _isRunning);
or even just creating a property accessor
bool _isRunning {
get {
return _vx != 0;
}
}
As for your actual question; I can't see your transitions but I'm assuming there's something wrong with them, keep trying to debug it by removing SetBools, and check the Animator on what is being triggered. The Any State -> Idle looks suspicious.
I stumbled across a problem while working with the book "Unity in Action". At the end of chapter 3 you'd end up with the basics for a simple fps game. It's basically a player (camera attached to it) in a simple and small level which only exists out of a number of cubes forming walls and the floor etc. These cubes all have box collider on them. Now the player is also able to shoot at moving enemies which are also able to shoot. This was done by Raycast/RaycastHit. All this worked perfectly so I wanted to add something that reassembles bullet holes, simply by instantiating a black sphere object on the wall where the fireball (this is the object the enemy and the player shoot) hits it. This works BUT sometimes the fireball object just goes through the wall. In case there is another wall behind it, the fireball object gets destroyed by this second wall and the desired sphere is created on the second wall instead of on the first wall.
I changed the speed in the fireball from 20 to 10 and then back to 20 and at a speed of 10, the success rate is around 19/20, while at a speed of 20 it's around 6/10.
Here is the code of the fireball which is supposed to check whether it hits the player (then health is deducted, that works fine) or hits the enemy (then the enemy falls over, also works fine) or hits the wall in which case the sphere should be created.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fireball : MonoBehaviour {
public float speed = 10.0f;
public int damage = 1;
[SerializeField] private GameObject wallHit;
private GameObject _wallHit;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
transform.Translate(0,0, speed * Time.deltaTime);
}
void OnTriggerEnter(Collider other){
RaycastHit hit;
PlayerCharacter player = other.GetComponent<PlayerCharacter>();
ReactiveTarget target = other.GetComponent<ReactiveTarget>();
WallBehavior wall = other.GetComponent<WallBehavior>();
if(player != null){
player.Hurt(damage);
}
if(target != null){
target.ReactToHit();
}
if(wall != null){
if(Physics.Raycast(transform.position, transform.forward, out hit)){
wall.WallWasHit(hit);
}
}
Destroy(this.gameObject);
}
}
As you can see one thing I tried was to give each wall a WallBehavior script, which looks like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WallBehavior : MonoBehaviour {
[SerializeField] private GameObject wallHit;
private GameObject _wallHit;
static int count = 0;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public void WallWasHit(RaycastHit hit){
count++;
Debug.Log("Wall was hit: " + count);
_wallHit = Instantiate(wallHit) as GameObject;
_wallHit.transform.position = hit.point;
}
}
But none of my attempts to understand why this happens so infrequently was successful so far and I hope someone can help me with this because I feel like might be crucial for my learning before I continue with the book! Thanks in advance. if further information are needed, I am happy to provide them. See the following picture for a better visualization of the issue.
EDIT:
As mentioned in the answers, I replaced the fireball script accordingly but I am not sure how to change the following script likewise. This script is on my camera which is on my player object. In the Update function the Fireball is instantiated and also given a movement, so I guess this causes the problems?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RayShooter : MonoBehaviour {
private Camera _camera;
[SerializeField] private GameObject fireballPrefab;
private GameObject _fireball;
void Start () {
_camera = GetComponent<Camera>();
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
void OnGUI(){
int size = 12;
float posX = _camera.pixelWidth/2 - size/4;
float posY = _camera.pixelHeight/2 - size/2;
GUI.Label(new Rect(posX, posY, size, size), "X");
}
// Update is called once per frame
void Update () {
if(Input.GetMouseButtonDown(0)){
Vector3 point = new Vector3(_camera.pixelWidth/2, _camera.pixelHeight/2, 0);
_fireball = Instantiate(fireballPrefab) as GameObject;
_fireball.transform.position = transform.TransformPoint(Vector3.forward * 1.5f);
_fireball.transform.rotation = transform.rotation;
Ray ray2 = _camera.ScreenPointToRay(point);
RaycastHit hit;
if(Physics.Raycast(ray2, out hit)){
GameObject hitObject = hit.transform.gameObject;
ReactiveTarget target = hitObject.GetComponent<ReactiveTarget>();
if(target !=null){
target.ReactToHit();
}
}
}
}
}
This is not how to move a Rigidbody Object and moving it like this could cause so many issues including the one mentioned in your question. Objects with Rigidbody should be moved with the Rigidbody component and with the functions like Rigidbody.MovePosition, Rigidbody.AddForce and Rigidbody.velocity not by the transform or transform.Translate.
Also, you should move the Rigidbody Object in the FixedUpdate function instead of the Update function. If you are moving your other Rigidbody Objects by their transform then you must fix them too. The example below replaces transform.Translate with Rigidbody.MovePosition in the Fireball script:
public float speed = 10.0f;
public int damage = 1;
[SerializeField]
private GameObject wallHit;
private GameObject _wallHit;
public Rigidbody rb;
// Use this for initialization
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void FixedUpdate()
{
//Move to towards Z-axis
Vector3 pos = new Vector3(0, 0, 1);
pos = pos.normalized * speed * Time.deltaTime;
rb.MovePosition(rb.transform.position + pos);
}
void OnTriggerEnter(Collider other)
{
RaycastHit hit;
PlayerCharacter player = other.GetComponent<PlayerCharacter>();
ReactiveTarget target = other.GetComponent<ReactiveTarget>();
WallBehavior wall = other.GetComponent<WallBehavior>();
if (player != null)
{
player.Hurt(damage);
}
if (target != null)
{
target.ReactToHit();
}
if (wall != null)
{
if (Physics.Raycast(transform.position, transform.forward, out hit))
{
wall.WallWasHit(hit);
}
}
Destroy(this.gameObject);
}
If you still run into issues, use Rigidbody.velocity instead:
void FixedUpdate()
{
Vector3 pos = Vector3.zero;
pos.z = speed * Time.deltaTime;
rb.velocity = pos;
}
Sometimes, depending on the size of the object and the speed it is moving by, you many need to set its Rigidbody Interpolate from None to Interpolate and Collision Detection to Continuous.
Don't forget to remove the code in the Update function.
EDIT:
I looked at your project and found new problems:
1.You enabled IsTrigger on your "Fireball" GameObject. Please uncheck the IsTrigger on the collider.
2.You just want to shoot a bullet. The force should be added once only not every FixedUpdate. Add the force in the Start function instead of the FixedUpdate function. Use Rigidbody.velocity instead of Rigidbody.MovePosition.
Remove the FixedUpdate function and the code inside it.
This should be your new Start function:
void Start()
{
rb = GetComponent<Rigidbody>();
Vector3 pos = transform.forward * speed * Time.deltaTime;
rb.velocity = pos;
}
I imported Unity Standard Assets cross platform input successfully
In imported cross Platfrom script UnityStandardAssets.CrossCrossPlatformInput is working perfectly
but when i use it in CharacterController2D script that not respoonding
shows errors
unknown package actually namespace in C#
and in file path for standard assets is
Assets\Standard Assets\CrossPlatformInput\Scripts
and CharacterController2D path is
Assets\Scripts
following CharacterController2D script is
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement; // include so we can load new scenes
using UnityStandardAssets.CrossCrossPlatformInput; //even this line shows error
public class CharacterController2D : MonoBehaviour {
// player controls
[Range(0.0f, 10.0f)] // create a slider in the editor and set limits on moveSpeed
public float moveSpeed = 3f;
public float jumpForce = 600f;
// player health
public int playerHealth = 1;
// LayerMask to determine what is considered ground for the player
public LayerMask whatIsGround;
// Transform just below feet for checking if player is grounded
public Transform groundCheck;
// player can move?
// we want this public so other scripts can access it but we don't want to show in editor as it might confuse designer
[HideInInspector]
public bool playerCanMove = true;
// SFXs
public AudioClip coinSFX;
public AudioClip deathSFX;
public AudioClip fallSFX;
public AudioClip jumpSFX;
public AudioClip victorySFX;
// private variables below
// store references to components on the gameObject
Transform _transform;
Rigidbody2D _rigidbody;
Animator _animator;
AudioSource _audio;
// hold player motion in this timestep
float _vx;
float _vy;
// player tracking
bool facingRight = true;
bool isGrounded = false;
bool isRunning = false;
bool canDoubleJump = false;
// store the layer the player is on (setup in Awake)
int _playerLayer;
// number of layer that Platforms are on (setup in Awake)
int _platformLayer;
void Awake () {
// get a reference to the components we are going to be changing and store a reference for efficiency purposes
_transform = GetComponent<Transform> ();
_rigidbody = GetComponent<Rigidbody2D> ();
if (_rigidbody==null) // if Rigidbody is missing
Debug.LogError("Rigidbody2D component missing from this gameobject");
_animator = GetComponent<Animator>();
if (_animator==null) // if Animator is missing
Debug.LogError("Animator component missing from this gameobject");
_audio = GetComponent<AudioSource> ();
if (_audio==null) { // if AudioSource is missing
Debug.LogWarning("AudioSource component missing from this gameobject. Adding one.");
// let's just add the AudioSource component dynamically
_audio = gameObject.AddComponent<AudioSource>();
}
// determine the player's specified layer
_playerLayer = this.gameObject.layer;
// determine the platform's specified layer
_platformLayer = LayerMask.NameToLayer("Platform");
}
// this is where most of the player controller magic happens each game event loop
void Update()
{
// exit update if player cannot move or game is paused
if (!playerCanMove || (Time.timeScale == 0f))
return;
// determine horizontal velocity change based on the horizontal input
_vx = CrossPlatformInputManager.GetAxisRaw ("Horizontal");
// Determine if running based on the horizontal movement
if (_vx != 0)
{
isRunning = true;
} else {
isRunning = false;
}
// set the running animation state
_animator.SetBool("Running", isRunning);
// get the current vertical velocity from the rigidbody component
_vy = _rigidbody.velocity.y;
// Check to see if character is grounded by raycasting from the middle of the player
// down to the groundCheck position and see if collected with gameobjects on the
// whatIsGround layer
isGrounded = Physics2D.Linecast(_transform.position, groundCheck.position, whatIsGround);
///checking if can do double jump or not
if (isGrounded)
{
canDoubleJump = true;
}
// Set the grounded animation states
_animator.SetBool("Grounded", isGrounded);
if(isGrounded && CrossPlatformInputManager.GetButtonDown("Jump")) // If grounded AND jump button pressed, then allow the player to jump
{
doJump ();
}
else if(canDoubleJump && CrossPlatformInputManager.GetButtonDown("Jump"))
{
doJump ();
canDoubleJump = false; //disabling dpuble jump after single jump
}
// If the player stops jumping mid jump and player is not yet falling
// then set the vertical velocity to 0 (he will start to fall from gravity)
if(CrossPlatformInputManager.GetButtonUp("Jump") && _vy>0f)
{
_vy = 0f;
}
// Change the actual velocity on the rigidbody
_rigidbody.velocity = new Vector2(_vx * moveSpeed, _vy);
// if moving up then don't collide with platform layer
// this allows the player to jump up through things on the platform layer
// NOTE: requires the platforms to be on a layer named "Platform"
Physics2D.IgnoreLayerCollision(_playerLayer, _platformLayer, (_vy > 0.0f));
}
// Checking to see if the sprite should be flipped
// this is done in LateUpdate since the Animator may override the localScale
// this code will flip the player even if the animator is controlling scale
void LateUpdate()
{
// get the current scale
Vector3 localScale = _transform.localScale;
if (_vx > 0) // moving right so face right
{
facingRight = true;
} else if (_vx < 0) { // moving left so face left
facingRight = false;
}
// check to see if scale x is right for the player
// if not, multiple by -1 which is an easy way to flip a sprite
if (((facingRight) && (localScale.x<0)) || ((!facingRight) && (localScale.x>0))) {
localScale.x *= -1;
}
// update the scale
_transform.localScale = localScale;
}
// if the player collides with a MovingPlatform, then make it a child of that platform
// so it will go for a ride on the MovingPlatform
void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag=="MovingPlatform")
{
this.transform.parent = other.transform;
}
}
// if the player exits a collision with a moving platform, then unchild it
void OnCollisionExit2D(Collision2D other)
{
if (other.gameObject.tag=="MovingPlatform")
{
this.transform.parent = null;
}
}
// do what needs to be done to freeze the player
void FreezeMotion() {
playerCanMove = false;
_rigidbody.isKinematic = true;
}
// do what needs to be done to unfreeze the player
void UnFreezeMotion() {
playerCanMove = true;
_rigidbody.isKinematic = false;
}
// play sound through the audiosource on the gameobject
void PlaySound(AudioClip clip)
{
_audio.PlayOneShot(clip);
}
// public function to apply damage to the player
public void ApplyDamage (int damage) {
if (playerCanMove) {
playerHealth -= damage;
if (playerHealth <= 0) { // player is now dead, so start dying
PlaySound(deathSFX);
StartCoroutine (KillPlayer ());
}
}
}
//Public Jump function
public void doJump()
{
// reset current vertical motion to 0 prior to jump
_vy = 0f;
// add a force in the up direction
_rigidbody.AddForce (new Vector2 (0, jumpForce));
// play the jump sound
PlaySound(jumpSFX);
}
//EnemyJump function
public void EnemyJump()
{
doJump ();
}
// public function to kill the player when they have a fall death
public void FallDeath () {
if (playerCanMove) {
playerHealth = 0;
PlaySound(fallSFX);
StartCoroutine (KillPlayer ());
}
}
// coroutine to kill the player
IEnumerator KillPlayer()
{
if (playerCanMove)
{
// freeze the player
FreezeMotion();
// play the death animation
_animator.SetTrigger("Death");
// After waiting tell the GameManager to reset the game
yield return new WaitForSeconds(2.0f);
if (GameManager.gm) // if the gameManager is available, tell it to reset the game
GameManager.gm.ResetGame();
else // otherwise, just reload the current level
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
public void CollectCoin(int amount) {
PlaySound(coinSFX);
if (GameManager.gm) // add the points through the game manager, if it is available
GameManager.gm.AddPoints(amount);
}
// public function on victory over the level
public void Victory() {
PlaySound(victorySFX);
FreezeMotion ();
_animator.SetTrigger("Victory");
if (GameManager.gm) // do the game manager level compete stuff, if it is available
GameManager.gm.LevelCompete();
}
// public function to respawn the player at the appropriate location
public void Respawn(Vector3 spawnloc) {
UnFreezeMotion();
playerHealth = 1;
_transform.parent = null;
_transform.position = spawnloc;
_animator.SetTrigger("Respawn");
}
}
This is first time that I have used cross platform input
so I don't even know why this error is showing
Sorry to Bother you guys.
I think i found my error in this code
actually i mistakenly write
using UnityStandardAssets.CrossCrossPlatformInput;
instead of
using UnityStandardAssets.CrossPlatformInput;
that's why it's showing error Unknown Namespace Under Standard Unity Assests
Actually I am new to Unity and also new to game development
i think that's why this problem happen
also, you need to use a compiler definition as shown, i was stuck on it for a long time, but found it written in the guidelines that come along with standard asset package..
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;
// CROSS_PLATFORM_INPUT
public class Player : MonoBehaviour
{
public float speed = 6f;
Vector2 moveVelocity;
public Rigidbody2D rb;
Vector2 movement;
void Update()
{
Vector2 moveInput = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
moveVelocity = moveInput * speed;
}
void FixedUpdate()
{
rb.MovePosition(rb.position + moveVelocity * Time.fixedDeltaTime);
}
public void Up()
{
FixedUpdate();
}
private void OnTriggerEnter2D(Collider2D target)
{
if (target.tag == "Enemy")
{
GameManager.instance.PlayerDied();
Debug.Log("ok");
}
if (target.tag == "Finish")
{
Debug.Log("ok");
GameManager.instance.PlayerWin();
}
}
}
I am building a multiplayer game using unity. The main player is a prefab spawned using network manager and contains Player tag and the. Down below is the enemy attack script that searches of Player tag but in multiplayer get only one Player in return.How can i alter it so that the Gameobject player is an array and playerHealth can getcomponent PlayerHealth.
public class EnemyAttack : MonoBehaviour
{
public float timeBetweenAttacks = 0.5f; // The time in seconds between each attack.
public int attackDamage = 10; // The amount of health taken away per attack.
Animator anim; // Reference to the animator component.
GameObject player; // Reference to the player GameObject.
PlayerHealth playerHealth; // Reference to the player's health.
EnemyHealth enemyHealth; // Reference to this enemy's health.
bool playerInRange; // Whether player is within the trigger collider and can be attacked.
float timer; // Timer for counting up to the next attack.
void Awake ()
{
// Setting up the references.
player = GameObject.FindGameObjectWithTag ("Player");
playerHealth = player.GetComponent <PlayerHealth> ();
enemyHealth = GetComponent<EnemyHealth>();
anim = GetComponent <Animator> ();
}
void OnTriggerEnter (Collider other)
{
// If the entering collider is the player...
if(other.gameObject == player)
{
// ... the player is in range.
playerInRange = true;
}
}
void OnTriggerExit (Collider other)
{
// If the exiting collider is the player...
if(other.gameObject == player)
{
// ... the player is no longer in range.
playerInRange = false;
}
}
void Update ()
{
// Add the time since Update was last called to the timer.
timer += Time.deltaTime;
// If the timer exceeds the time between attacks, the player is in range and this enemy is alive...
if(timer >= timeBetweenAttacks && playerInRange && enemyHealth.currentHealth > 0)
{
// ... attack.
Attack ();
}
// If the player has zero or less health...
if(playerHealth.currentHealth <= 0)
{
// ... tell the animator the player is dead.
anim.SetTrigger ("PlayerDead");
}
}
void Attack ()
{
// Reset the timer.
timer = 0f;
// If the player has health to lose...
if(playerHealth.currentHealth > 0)
{
// ... damage the player.
playerHealth.TakeDamage (attackDamage);
}
}
}
You should need to use FindGameObjectsWithTag with invoke repeating. A untested code snippet given below:
public GameObject[] playersList;
void Start() {
//Invokes the method methodName in time seconds,
//then repeatedly every repeatRate seconds.
InvokeRepeating("CheckPlayers", 2.0f, 0.3f);
}
public void CheckPlayers(){
//assign player in the player list
playersList= GameObject.FindGameObjectsWithTag ("Player");
//now playersList contains all player, do what you want with it
}
This is unity 2d angry bird style game example. I working on resetter codes. Resetter code below (I changed some parts). I using ball on this project instead of birds. So, I want to if ball is stoped after to throw load new ball to catapult. But It doesn't work correctly. First of all. I wrote if ball count == 0 clone the object. But its alwaws clonning when ball was stoped. On the other hand I cant use cloned object for throwing. Cloned object not on the catapult. Sorry for my bad english but this problem my last
phase on this game.
for example
https://www.dropbox.com/s/h3gwinw8chyeh59/error.png?dl=0
This is game tutorial link.
http://unity3d.com/learn/tutorials/modules/beginner/live-training-archive/making-angry-birds-style-game
using UnityEngine;
using System.Collections;
public class Resetter : MonoBehaviour {
public Rigidbody2D projectile; // The rigidbody of the projectile
public float resetSpeed = 0.025f; // The angular velocity threshold of the projectile, below which our game will reset
private float resetSpeedSqr; // The square value of Reset Speed, for efficient calculation
private SpringJoint2D spring; // The SpringJoint2D component which is destroyed when the projectile is launched
public int BallCount; // I using this value for I need new ball or not
public Rigidbody2D projectileSD; // Ball
void Start ()
{
BallCount = 1;
// Calculate the Resset Speed Squared from the Reset Speed
resetSpeedSqr = resetSpeed * resetSpeed;
// Get the SpringJoint2D component through our reference to the GameObject's Rigidbody
spring = projectile.GetComponent <SpringJoint2D>();
}
void Update () {
// If the spring had been destroyed (indicating we have launched the projectile) and our projectile's velocity is below the threshold...
if (spring == null && projectile.velocity.sqrMagnitude < resetSpeedSqr) {
// ... call the Reset() function
// Reset ();
if (BallCount == 0 );
{
ObjeyiKlonla();
}
}
}
void ObjeyiKlonla() { // Clone object
Rigidbody2D clone;
clone = Instantiate (projectileSD, transform.position, transform.rotation) as Rigidbody2D;
clone.velocity = transform.TransformDirection (Vector3.forward * 1);
BallCount ++;
}
void OnTriggerExit2D (Collider2D other) {
// If the projectile leaves the Collider2D boundary...
if (other.rigidbody2D == projectile) {
// ... call the Reset() function
//Reset ();
}
}
void Reset () {
// The reset function will Reset the game by reloading the same level
//Application.LoadLevel (Application.loadedLevel);
BallCount =0;
}
}
Try this.
void Update(){
if(projectile.GetComponent <SpringJoint2D>() && projectile.velocity.sqrMagnitude < resetSpeedSqr)
{
if (BallCount <= 0 );
{
ObjeyiKlonla();
}
}
}