Collision Detection for Character Crouching Not Working in Unity 3D - unity3d

I was following a tutorial but I'm having trouble with the CheckCollisionOverlap() function. It's meant to check for a collision over the player's head when the player is crouching, but for some reason he won't stand back up (or stop walking in place).
If I comment out PhysicsUpdate() and CheckCollisionOverlap(), he will crouch, walk crouch, and stand up from crouch, so I know the problem has to exist within that logic.
In the tutorial comments section, someone mentioned that they changed the value of the layermask. I named a layermask Player and assigned it to layer 8 but that still didn't do anything.
Tutorial Link https://www.youtube.com/watch?v=QVxvwRAYeHU
using UnityEngine;
public class CrouchingState : State
{
float playerSpeed;
bool belowCeiling;
bool crouchHeld;
bool grounded;
float gravityValue;
Vector3 currentVelocity;
public CrouchingState(Character _character, StateMachine _stateMachine):base(_character, _stateMachine)
{
character = _character;
stateMachine = _stateMachine;
}
public override void Enter()
{
base.Enter();
character.animator.SetTrigger("crouch");
belowCeiling = false;
crouchHeld = false;
gravityVelocity.y = 0;
playerSpeed = character.crouchSpeed;
character.controller.height = character.crouchColliderHeight;
character.controller.center = new Vector3(0f, character.crouchColliderHeight / 2f, 0f);
grounded = character.controller.isGrounded;
gravityValue = character.gravityValue;
}
public override void Exit()
{
base.Exit();
character.controller.height = character.normalColliderHeight;
character.controller.center = new Vector3(0f, character.normalColliderHeight / 2f, 0f);
gravityVelocity.y = 0f;
character.playerVelocity = new Vector3(input.x, 0, input.y);
character.animator.SetTrigger("move");
}
public override void HandleInput()
{
base.HandleInput();
if (crouchAction.triggered && !belowCeiling)
{
crouchHeld = true;
}
input = moveAction.ReadValue<Vector2>();
velocity = new Vector3(input.x, 0, input.y);
velocity = velocity.x * character.cameraTransform.right.normalized + velocity.z * character.cameraTransform.forward.normalized;
velocity.y = 0f;
}
public override void LogicUpdate()
{
base.LogicUpdate();
character.animator.SetFloat("speed", input.magnitude, character.speedDampTime, Time.deltaTime);
if (crouchHeld)
{
stateMachine.ChangeState(character.standing);
}
}
public override void PhysicsUpdate()
{
base.PhysicsUpdate();
belowCeiling = CheckCollisionOverlap(character.transform.position + Vector3.up * character.normalColliderHeight);
gravityVelocity.y += gravityValue * Time.deltaTime;
grounded = character.controller.isGrounded;
if (grounded && gravityVelocity.y < 0)
{
gravityVelocity.y = 0f;
}
currentVelocity = Vector3.Lerp(currentVelocity, velocity, character.velocityDampTime);
character.controller.Move(currentVelocity * Time.deltaTime * playerSpeed + gravityVelocity * Time.deltaTime);
if (velocity.magnitude > 0)
{
character.transform.rotation = Quaternion.Slerp(character.transform.rotation, Quaternion.LookRotation(velocity), character.rotationDampTime);
}
}
public bool CheckCollisionOverlap(Vector3 targetPositon)
{
int layerMask = 1 << 8;
layerMask = ~layerMask;
RaycastHit hit;
Vector3 direction = targetPositon - character.transform.position;
if (Physics.Raycast(character.transform.position, direction, out hit, character.normalColliderHeight, layerMask))
{
Debug.DrawRay(character.transform.position, direction * hit.distance, Color.yellow);
return true;
}
else
{
Debug.DrawRay(character.transform.position, direction * character.normalColliderHeight, Color.white);
return false;
}
}
}

I had to change all the layers of the children in the player gameobject as well. Not really sure why that worked, but its responding.

Related

Unity Game BreakOut ball loses speed and direction

I just finished a BreakOut style game but there is a bug where sometimes the ball gets stuck to the edges of the map with no direction or speed as shown in the screenshot
What I see is that it happens when the ball completely loses trajectory or speed, but could not solve the error
enter image description here
my code
public class Ball : MonoBehaviour
{
[SerializeField] Rigidbody2D rigidbody2D;
Vector2 moveDirection;
Vector2 currentVelocity;
float velocity=10;
//GameManager gameManager;
Transform paddle;
[SerializeField] AudioController audioController;
[SerializeField] AudioClip bounceSfx;
[SerializeField] AudioClip dieSfx;
public bool superBall;
[SerializeField] float superBallTime=10;
[SerializeField]float yMinSpeed = 10;
[SerializeField]TrailRenderer trailRenderer;
public bool SuperBall
{
get=> superBall;
set{
superBall=value;
if(superBall)
StartCoroutine(ResetSuperBall());
}
}
// Start is called before the first frame update
void Start()
{
//rigidbody2D = GetComponent<Rigidbody2D>();
//rigidbody2D.velocity = Vector2.up*velocity*Time.deltaTime;
GameManager.Instance = FindObjectOfType<GameManager>();
paddle = transform.parent;
}
// Update is called once per frame
void Update()
{
currentVelocity = rigidbody2D.velocity;
if (Mathf.Abs(currentVelocity.y) < 3 && Mathf.Abs(currentVelocity.y) < 3 && GameManager.Instance.ballOnGame)
{
velocity = 10;
rigidbody2D.velocity = Vector2.up * velocity ;
}
if (Mathf.Abs(currentVelocity.y) + Mathf.Abs(currentVelocity.y) < 10 && GameManager.Instance.ballOnGame)
{
velocity = 10;
rigidbody2D.velocity = Vector2.up * velocity ;
}
if (velocity <10 && GameManager.Instance.ballOnGame)
{
velocity = 10;
rigidbody2D.velocity = Vector2.up * velocity ;
}
if ((Input.GetKey(KeyCode.W) && GameManager.Instance.ballOnGame == false)||(Input.GetKey(KeyCode.Space) && GameManager.Instance.ballOnGame == false))
{
rigidbody2D.velocity = Vector2.up * velocity ;
transform.parent = null;
GameManager.Instance.ballOnGame = true;
rigidbody2D.isKinematic = false;
rigidbody2D.AddForce(new Vector3(velocity, velocity, 0));
if (!GameManager.Instance.GameStarted)
{
GameManager.Instance.GameStarted = true;
}
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.transform.CompareTag("Brick") && superBall)
{
rigidbody2D.velocity = currentVelocity;
return;
}
moveDirection=Vector2.Reflect(currentVelocity,collision.GetContact(0).normal);
if (Mathf.Abs(moveDirection.y) < yMinSpeed)
{
//permitir velocidad minima
moveDirection.y = yMinSpeed*Mathf.Sign(moveDirection.y);
}
rigidbody2D.velocity=moveDirection;
audioController.PlaySfx(bounceSfx);
if (collision.transform.CompareTag("BottomLimit"))
{
if(GameManager.Instance != null)
{
GameManager.Instance.PlayerLives--;
audioController.PlayDie(dieSfx);
if (GameManager.Instance.PlayerLives > 0)
{
rigidbody2D.velocity = Vector2.zero;
transform.SetParent(paddle);
transform.localPosition = new Vector2(0, 0.65f);
GameManager.Instance.ballOnGame = false;
}
}
}
}
IEnumerator ResetSuperBall()
{
trailRenderer.enabled = true;
yield return new WaitForSeconds(superBallTime);
trailRenderer.enabled = false;
GameManager.Instance.powerIsActive = false;
superBall = false;
}
}
This is a common issue with Rigidbodies at low velocities. The physics engine implements a Physics2D.velocityThreshold that is designed to dampen slow bounces and calm down a pile of Rigidbodies.
The default value for velocityThreshold is 1, meaning that the x or y component of the velocity that is slower will be floored to 0.
To resolve this issue you can simply lower the value to 0.001. You can do it in the Physcs2d tab located at Edit->ProjectSettings->Physics2d

RayCastAll from Camera to Player Not Working

Trying to run a raycast from my camera to Z = 0 that will hit objects on the TransparentFX layer and temporarily make them transparent as they are likely blocking the view of the player. But the raycast never hits anything.
Camera
https://imgur.com/lyTo8OZ
Tree
https://imgur.com/bgNiMWR
ClearSight.cs
[RequireComponent(typeof(Camera))]
public class ClearSight : MonoBehaviour
{
[SerializeField]
private LayerMask raycastLayers;
// Update is called once per frame
void Update()
{
Vector3 forward = transform.TransformDirection(Vector3.forward) * 10;
Debug.DrawRay(transform.position, forward, Color.green);
RaycastHit2D[] hits = Physics2D.RaycastAll(transform.position, transform.TransformDirection(Vector3.forward), 10f, raycastLayers);
if(hits != null && hits.Length > 0)
{
Debug.Log("Found objects blocking player!");
foreach(RaycastHit2D hit in hits)
{
Debug.Log("Making " + hit.transform.gameObject.name + " transparent!");
AutoTransparent at = hit.transform.GetComponent<AutoTransparent>();
if(at == null)
{
at = hit.transform.gameObject.AddComponent<AutoTransparent>();
}
at.MakeTransparent();
}
}
}
}
AutoTransparent.cs
[RequireComponent(typeof(SpriteRenderer))]
public class AutoTransparent : MonoBehaviour
{
[SerializeField]
private SpriteRenderer[] renderTargets;
[SerializeField]
private float transparentRecoveryTime = 0.1f;
private bool isTransparent = false;
private float transparencyTimer = 0;
private void Update()
{
if (isTransparent)
{
UpdateTransparencyTimer();
}
}
private void UpdateTransparencyTimer()
{
transparencyTimer += Time.deltaTime / transparentRecoveryTime;
if(transparencyTimer >= 1)
{
MakeOpaque();
}
}
public void MakeTransparent()
{
transparencyTimer = 0;
if (!isTransparent)
{
isTransparent = true;
foreach (SpriteRenderer renderer in renderTargets)
{
Color c = renderer.color;
renderer.color = new Color(c.r, c.g, c.b, 0.3f);
}
}
}
public void MakeOpaque()
{
isTransparent = false;
foreach(SpriteRenderer renderer in renderTargets)
{
Color c = renderer.color;
renderer.color = new Color(c.r, c.g, c.b, 1);
}
}
}
Figured it out. I was using RaycastHit2D and Physics2D.RaycastAll, which uses Vector2 parameters so the Z forward variable was being taken out of the equation. Switched up to Box Collider and Physics.RaycastAll and it works great.

Smooth Player Ball Rolling - Unity 3D

I was trying to achieve this kind of player ball movement:
Catch Up (Ketchapp)
From my side I have tried and record a video of my current implementation:
CatchUpBallMovementDemo
Two kinds of problem, I was facing:
ball making so much jerk while moving on the plain track that I hope you have clearly noticed in my recorded video
when ball reach left or right edge and you try to swipe its making jerk again rather than remain restricted because clamping related code already added
I have just created a demo project so here I am providing the link for it so personally you can check and provide me a suggestion for making ball movement perfect.
Demo Project Source Link: CatchUpBallDemo
Demo Project SIZE 20MB
What at present making jerk in ball movement that I can't able to decide, whether its following camera jerk, whether ball not moving properly though I have created a plain track for checking purpose.
Ball Inspector Detail:
Complete code added within the working demo project. Share your suggestions with me to solve this.
Code Scripts:
BallController
[RequireComponent (typeof(Rigidbody))]
public class BallController : MonoBehaviour
{
//
private Rigidbody myRigidBody;
private bool isJumper;
private bool allowSpeedIncrease;
private BallInputHandler ballInputHandler;
private float speed;
private float speedMilestone;
private float jumpCounter;
private float scoreElapsedTime;
[SerializeField]
private bool isGrounded;
//
public float ballHorzRange;
public float ballStartSpeed;
public float ballTopSpeed;
public float smoothnessValue;
public float smoothnessX;
private void Awake ()
{
DoOnAwake ();
}
private void DoOnAwake ()
{
ballInputHandler = GetComponent<BallInputHandler> ();
myRigidBody = GetComponent<Rigidbody> ();
speed = ballStartSpeed;
speedMilestone = ballStartSpeed;
}
public void Start ()
{
DoOnStart ();
}
private void DoOnStart ()
{
// assinging player transform to camera to follow
Camera.main.GetComponent<CameraFollow> ().FollowPlayer (transform);
}
void Update ()
{
// slowly increase ball moving speed
if (allowSpeedIncrease) {
speed += Time.deltaTime;
if (speed >= speedMilestone) {
allowSpeedIncrease = false;
speed = speedMilestone;
}
}
}
void FixedUpdate ()
{
// do jumping
if (isJumper) {
jumpCounter++;
if (jumpCounter >= 3) {
isJumper = false;
jumpCounter = 0;
}
myRigidBody.AddForce (Vector3.up * 700f);
}
// applying continuous forward velocity
Vector3 nextVelocity = myRigidBody.velocity;
nextVelocity.x = ballInputHandler.horizontalInput * smoothnessX;
nextVelocity.z = speed;
if (isGrounded) {
nextVelocity.y = 0;
} else if (!isJumper) {
nextVelocity.y -= speed * 0.1f;
}
myRigidBody.velocity = nextVelocity.normalized * speed;
ClampingBallMovement ();
}
// ball horizontal movement limitation
private void ClampingBallMovement ()
{
Vector3 currRigidbodyPos = myRigidBody.position;
if (currRigidbodyPos.x <= -ballHorzRange || currRigidbodyPos.x >= ballHorzRange) {
currRigidbodyPos.x = Mathf.Clamp (currRigidbodyPos.x, -ballHorzRange, ballHorzRange);
myRigidBody.position = currRigidbodyPos;
}
}
void OnTriggerEnter (Collider other)
{
if (other.CompareTag (GameConstants.TAG_TRACK_SPAWNER)) {
GameController.Instance.SpawnPlateform ();
} else if (other.CompareTag (GameConstants.TAG_TRACK_DESTROYER)) {
Destroy (other.transform.parent.gameObject);
}
}
}
BallMeshRolling
public class BallMeshRolling : MonoBehaviour
{
private Vector3 ballLastPosition;
void Start ()
{
ballLastPosition = transform.parent.position;
}
void Update ()
{
// implementation-1
float speed = Vector3.Distance (transform.parent.position, ballLastPosition) * 30f;
transform.RotateAround (transform.position, Vector3.right, speed);
// float dragDifference = (transform.position.x - ballLastPosition.x) * 30f;
// transform.RotateAround (transform.position, Vector3.forward, dragDifference);
ballLastPosition = transform.parent.position;
}
}
CameraFollow
public class CameraFollow : MonoBehaviour
{
//
private Vector3 newPos;
private Vector3 initialPosition;
//
public Transform player;
public Vector3 offSet;
void Awake ()
{
initialPosition = transform.position;
}
void LateUpdate ()
{
if (!player)
return;
newPos = player.position + offSet;
newPos.x = ReMap (newPos.x);
newPos.y = Mathf.Clamp (newPos.y, initialPosition.y, initialPosition.y + 1f);
// transform.position = newPos;
transform.position = Vector3.Lerp (transform.position, newPos, 10f * Time.deltaTime);
}
public void FollowPlayer (Transform target)
{
player = target;
ResetCamera ();
}
public float ReMap (float value, float from1 = -4f, float to1 = 4f, float from2 = -2.5f, float to2 = 2.5f)
{
return (value - from1) / (to1 - from1) * (to2 - from2) + from2;
}
public void ResetCamera ()
{
transform.position = initialPosition;
}
}
I could solve the second problem by simply adding this to BallController.ClampingBallMovement():
private void ClampingBallMovement ()
{
Vector3 currRigidbodyPos = myRigidBody.position;
if (currRigidbodyPos.x <= -ballHorzRange || currRigidbodyPos.x >= ballHorzRange) {
currRigidbodyPos.x = Mathf.Clamp (currRigidbodyPos.x, -ballHorzRange, ballHorzRange);
myRigidBody.position = currRigidbodyPos;
}
// I ADDED THIS
// Clamp the velocity as well
if (currRigidbodyPos.x <= -ballHorzRange && myRigidBody.velocity.x < 0 || currRigidbodyPos.x >= ballHorzRange && myRigidBody.velocity.x > 0)
{
myRigidBody.velocity = new Vector3(0, myRigidBody.velocity.y, myRigidBody.velocity.z);
}
}
you clamped the position but did not clamp the velocity as well.
I could not reproduce the first jerking arround on my PC.

Making a volleyball game, overlap not working

I'm making a 2D game on Unity and I created an overlap to see if the ball is on the hit area. However, whenever I push the hit button, the ball is hit even if it is away of the player. I am sending the code for the Player, which contains what is needed so far, to see what may have gone wrong. Supposedly with the foreach hitCollider in hitColliders it should be fixed but it is not working I and just can´t wrap my mind around it.
public int speed;
public bool estoyFloor, subiendo, bajando;
public bool canRight, canLeft;
public bool canMove;
public float posYinit;
public Vector3 posInitPlayer;
bool m_Started;
public LayerMask m_LayerMask;
public GameObject volleyBall;
// Use this for initialization
void Start () {
m_Started = true;
}
void FixedUpdate()
{
Collider2D[] hitColliders = Physics2D.OverlapBoxAll(gameObject.transform.position, transform.localScale / 2, 0);
foreach (Collider2D hitCollider in hitColliders)
{
if (Input.GetButtonDown("Fire1"))
{
volleyBall.GetComponent<Rigidbody2D>().velocity = Vector3.zero;
volleyBall.GetComponent<Rigidbody2D>().AddForce(new Vector3(300, 500));
}
}
}
void OnDrawGizmos()
{
Gizmos.color = Color.red;
if (m_Started)
Gizmos.DrawWireCube(transform.position, transform.localScale / 2);
}
// Update is called once per frame
void Update () {
if (Input.GetButtonDown("Fire1"))
canMove = true;
if (Input.GetAxisRaw("Horizontal") > 0 && canRight)
transform.position += Vector3.right * speed * Time.deltaTime;
if (Input.GetAxisRaw("Horizontal") < 0 && canLeft)
transform.position += Vector3.left * speed * Time.deltaTime;
if (Input.GetButtonDown("Jump") && estoyFloor)
{
subiendo = true;
posYinit = transform.position.y;
}
if (transform.position.y > posYinit + 2.5f)
{
subiendo = false;
bajando = true;
}
if (!estoyFloor && !subiendo)
bajando = true;
Debug.DrawLine(transform.position, transform.position + new Vector3(0, -1, 0), Color.red);
Debug.DrawLine(transform.position, transform.position + new Vector3(0.8f, 0, 0), Color.red);
Debug.DrawLine(transform.position, transform.position + new Vector3(1.5f, 0, 0), Color.red);
RaycastHit2D[] hitDown = Physics2D.LinecastAll(transform.position, transform.position + new Vector3(0, -1, 0));
RaycastHit2D[] hitsRight = Physics2D.LinecastAll(transform.position, transform.position + new Vector3(0.8f, 0, 0));
RaycastHit2D[] hitsLeft = Physics2D.LinecastAll(transform.position, transform.position + new Vector3(1.5f, 0, 0));
estoyFloor = false;
foreach (RaycastHit2D hit in hitDown)
{
if (hit.collider.name == "Floor")
{
bajando = false;
estoyFloor = true;
}
}
canRight = true;
foreach (RaycastHit2D hit in hitsRight)
{
if (hit.collider.tag == "Wall")
canRight = false;
}
canLeft = true;
foreach (RaycastHit2D hit in hitsLeft)
{
if (hit.collider.tag == "Wall")
canLeft = false;
}
if (subiendo)
transform.position += Vector3.up * speed * Time.deltaTime;
if (bajando)
transform.position += Vector3.down * speed * Time.deltaTime;
}
Your overlap box is probably colliding with the player it is on. Because you do not check if the collider belonged to the volleyball in your loop, you are hitting the ball no matter what. Try to get the transform from the collider and check its tag to see if it is a volleyball before adding force to the ball and see if that works. You could also use a layermask on your Overlap box check as well to ensure only volleyballs get detected.

Trying to add buff to my game

I'm new at programming. I started a Unity3D course at udemy, I already finished the course, but I'm trying to add a buff to my game. What I want is when my player gets that buff, his shot speed inscreases, I tried to do it but im getting this error when I collide with it
NullReferenceException: Object reference not set to an instance of an object
Powerup.OnTriggerEnter2D (UnityEngine.Collider2D other) (at Assets/Galaxy Shooter/Scripts/Powerup.cs:54)
EDIT
Album With usefull images
Player
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour {
public bool canTripleShoot = false;
public bool movSpeedBoost = false;
public bool shield = false;
[SerializeField]
private GameObject _laserPrefabs;
[SerializeField]
private GameObject _tripleShootPrefab;
[SerializeField]
private GameObject _shieldGameObject;
[SerializeField]
private GameObject _explosionPrefab;
[SerializeField]
private float _speed = 5.0f;
[SerializeField]
private GameObject[] _engines;
[SerializeField]
private float _fireRate = 0.25f;
private float _canFire = 0.0f;
public int playerHp = 3;
public int _hitcount = 0;
private UIManager _uiManager;
private GameManager _gameManager;
private SpawnManager _spawnManager;
private AudioSource _audioSource;
// Use this for initialization
void Start () {
_audioSource = GetComponent<AudioSource>();
_spawnManager = GameObject.Find("Spawn_Manager").GetComponent<SpawnManager>();
_uiManager = GameObject.Find("Canvas").GetComponent<UIManager>();
_gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
transform.position = new Vector3(0, 0, 0);
if(_uiManager != null)
{
_uiManager.UpdateLives(playerHp);
}
if(_spawnManager != null)
{
_spawnManager.StartSpawn();
}
}
// Update is called once per frame
void Update ()
{
Movement();
//ativar ao pressionar espaço ou botão esquerdo do mouse
if (Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButton(0))
{
Shoot();
}
}
//renderização e cooldown dos tiros
private void Shoot()
{
if (Time.time > _canFire)
{
_audioSource.Play();
if (canTripleShoot== true)
{
Instantiate(_tripleShootPrefab, transform.position, Quaternion.identity);
}
else
{
Instantiate(_laserPrefabs, transform.position + new Vector3(0, 0.95f, 0), Quaternion.identity);
}
_canFire = Time.time + _fireRate;
}
}
//calculo de dano
public void Damage()
{
if(shield == true)
{
shield = false;
_shieldGameObject.SetActive(false);
return;
}
_hitcount++;
if(_hitcount == 1)
{
_engines[0].SetActive(true);
}
if(_hitcount == 2)
{
_engines[1].SetActive(true);
}
playerHp--;
_uiManager.UpdateLives(playerHp);
if(playerHp < 1)
{
Instantiate(_explosionPrefab, transform.position, Quaternion.identity);
_gameManager.gameOver = true;
_uiManager.ShowTitleScreen();
Destroy(this.gameObject);
}
}
public void ShieldUp()
{
shield = true;
_shieldGameObject.SetActive(true);
}
//controle da velocidade de movimento e teleporte
private void Movement()
{
float controleHorizontal = Input.GetAxis("Horizontal");
float controleVertical = Input.GetAxis("Vertical");
//velocidade de movimento
if(movSpeedBoost == true)
{
transform.Translate(Vector3.up * _speed * controleVertical * Time.deltaTime * 2.0f);
transform.Translate(Vector3.right * _speed * controleHorizontal * Time.deltaTime * 2.0f);
}else
{
transform.Translate(Vector3.up * _speed * controleVertical * Time.deltaTime);
transform.Translate(Vector3.right * _speed * controleHorizontal * Time.deltaTime);
}
//limita jogar até o centro da tela
if (transform.position.y > 0)
{
transform.position = new Vector3(transform.position.x, 0, 0);
}
//limita jogar até a borda inferior
else if (transform.position.y < -4.2f)
{
transform.position = new Vector3(transform.position.x, -4.2f, 0);
}
//teleporta jogar se sair da tela na horizontal
else if (transform.position.x < -9.45f)
{
transform.position = new Vector3(9.45f, transform.position.y, 0);
}
else if (transform.position.x > 9.45f)
{
transform.position = new Vector3(-9.45f, transform.position.y, 0);
}
}
//duração triple shot
public IEnumerator TripleShotPowerDownRoutine()
{
yield return new WaitForSeconds(5.0f);
canTripleShoot = false;
}
public void TripleShotPowerUpOn()
{
canTripleShoot = true;
StartCoroutine(TripleShotPowerDownRoutine());
}
//duração boost de movimento
public IEnumerator MovSpeedBoostDownRoutine()
{
yield return new WaitForSeconds(5.0f);
movSpeedBoost = false;
}
//ativa boost de movimento e inicia contagem de duração
public void MovSpeedBoost()
{
movSpeedBoost = true;
StartCoroutine(MovSpeedBoostDownRoutine());
}
}
Laser
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Laser : MonoBehaviour {
[SerializeField]
public float _speed = 10.0f;
[SerializeField]
public bool _laserBoost = false;
// Use this for initialization
void Start () {
_laserBoost = false;
if (_laserBoost == true)
{
_speed = 100f;
}
}
// Update is called once per frame
void Update () {
//código gigante e dificil de decifrar ~irony
transform.Translate(Vector3.up * _speed * Time.deltaTime);
if (transform.position.y > 6f)
{
if(transform.parent != null)
{
Destroy(transform.parent.gameObject);
}
Destroy(gameObject);
}
}
public IEnumerator LaserBoostDuration()
{
yield return new WaitForSeconds(10f);
_laserBoost = false;
}
public void LaserBoost()
{
_laserBoost = true;
StartCoroutine(LaserBoostDuration());
}
}
Powerup
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Powerup : MonoBehaviour
{
[SerializeField]
private float _speed = 3.0f;
[SerializeField]
private int powerupID;
[SerializeField]
private AudioClip _clip;
// Update is called once per frame
void Update ()
{
//movimenta o powerup para baixo
transform.Translate(Vector3.down * _speed * Time.deltaTime);
//destroy o power ao sair da tela
if (transform.position.y <-7)
{
Destroy(this.gameObject);
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if(other.tag == "Player")
{
//acessa o player
Player player = other.GetComponent<Player>();
if(player != null)
{
if(powerupID == 0)
{
//ativa tripleshoot
player.TripleShotPowerUpOn();
}
else if(powerupID == 1)
{
//ativa speedboost
player.MovSpeedBoost();
}
else if(powerupID == 2)
{
//ativar shield
player.ShieldUp();
}
else if (powerupID == 3)
{
Laser laser = GameObject.Find("laser").GetComponent<Laser>();
laser.LaserBoost();
}
}
//detroy powerup
AudioSource.PlayClipAtPoint(_clip, transform.position);
Destroy(this.gameObject);
}
}
}
The error is occuring at
laser.LaserBoost();
One of the two:
1) you don't have a object named "laser" in Scene hierarchy;
2) this object exists but doesn't have a component of type Laser attached to it.
Edit: Now that I saw your image, I can confirm it is the case 1) above. You have a Prefab named "laser", but is doesn't exist in the Scene hierarchy. If you want it to come to existence only when needed, you must instantiate the Prefab in scene.
If you want to search for the Prefab by its name, there is a way, but you'll need to have a folder named Resources inside another named Assets... More info here
Instead, I suggest you another approach. First, you will need a reference to your Prefab in some object, depending on the logic of your program. You seem to have a GameManager class, there could be a good place. Add a new field inside there (if it is the case) like this:
[SerializeField]
public Laser laser
// (...)
Then, change the code that generates the error. GameObject.Find tries to find an object that already exists in scene. In your case, you want to instantiate a clone of a Prefab, by passing a reference to it. Something like this:
else if (powerupID == 3)
{
// I don't know for sure how can you access your GameManager in your program. I will suppose your player have a reference to it.
// You shall change the position depending on your game logic
Laser laserClone = (Laser) Instantiate(player.gameManager.laser, player.transform.position, player.transform.rotation);
laserClone.LaserBoost();
}
Now, select the object in Scene that will have the reference (again, I am supposing it is gameManager) to see its inspector, than fill the laser field with a reference to your Prefab that has a Laser component. Just be sure the clone object will be destroyed when it is not needed.
But... To be very honest, I don't think you will get the result you are expecting anyway. If what you want is just faster shoot rate, the way you're trying to do it now seems pretty convoluted to me. Why don't you do it just like the triple shoot you have? Add a flag inside your player, when it is true the fireRate value changes.