I know that this is a fairly regular question however having tried the solutions provided I have not been having much luck. Trying to get some object to collide in unity which worked, however the OnCollision2d call is not being made after they collide. Hoping to get some help on why this is happening.
The two classes provided here
[RequireComponent(typeof(SpriteRenderer))]
[RequireComponent(typeof(Rigidbody2D))]
public class Missile: MonoBehaviour
{
public bool dead = false, hostile = true;
public float speed = 30, rotatingSpeed= 200;
public GameObject target;
private BoxCollider2D bc;
private Rigidbody2D rb;
private SpriteRenderer sr;
private GameObject go;
public Missile() { Debug.Log("Constructed"); }
private void OnEnable()
{
Debug.Log("Missile Launched");
go = new GameObject("Missile");
go.tag = "Missile";
target = GameObject.FindGameObjectWithTag("Ship");
rb = go.AddComponent<Rigidbody2D> ();
sr = go.AddComponent<SpriteRenderer> ();
bc = go.AddComponent<BoxCollider2D>();
bc.size = new Vector2(2f, 2f);
//bc.isTrigger = true;
go.transform.position = new Vector3(0,0, 11);
sr.sprite = SpriteManager.current.GetSprite("Ships", "missile1");
}
private void FixedUpdate()
{
//sr.sprite = SpriteManager.current.GetSprite("Missiles", "missile1");
//Debug.Log(target);
if (!target) return;
var point2Target = (Vector2) go.transform.position - (Vector2) target.transform.position;
point2Target.Normalize();
float value = Vector3.Cross(point2Target, go.transform.right).z;
rb.angularVelocity = rotatingSpeed * value;
//Vector2 lastVel = rb.velocity;
rb.velocity = go.transform.right * speed;
//rb.AddForce(go.transform.right * speed);
}
public void setPosition(int x, int y)
{
go.transform.position = new Vector3(x,y,11);
}
private void OnCollisionEnter2D(Collision2D collision)
{
Debug.Log("hit");
Destroy (go, 0.02f);
}
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log("hit");
Destroy (go, 0.02f);
}
}
And the second class
[RequireComponent(typeof(SpriteRenderer))]
[RequireComponent(typeof(Rigidbody2D))]
public class Ship: MonoBehaviour
{
public int hull = 100, type = 1;
public bool dead = false;
public float speed = 5, rotatingSpeed= 200;
public GameObject target;
private BoxCollider2D bc;
private Rigidbody2D rb;
private SpriteRenderer sr;
private GameObject go;
public Ship() { Debug.Log("Constructor"); }
private void OnEnable()
{
Debug.Log("Ship Built");
go = new GameObject("Ship");
go.tag = "Ship";
//target = GameObject.FindGameObjectWithTag("Player");
rb = go.AddComponent<Rigidbody2D> ();
sr = go.AddComponent<SpriteRenderer> ();
bc = go.AddComponent<BoxCollider2D>();
bc.size = new Vector2(2f, 2f);;
bc.isTrigger = true;
go.transform.position = new Vector3(0,0,11);
sr.sprite = SpriteManager.current.GetSprite("Ships", "ship2");
//sr.sprite.transform.localScale = anyWidth;
//sr.sprite = SpriteManager.current.GetSprite("Missiles", "missile1");
}
void FixedUpdate ()
{
//Debug.Log(target);
GameObject[] missiles = GameObject.FindGameObjectsWithTag("Missile");
/*foreach (GameObject missile in missiles)
{
Vector2 point2Target = ((Vector2)go.transform.position - (Vector2) missile.transform.position);
if(point2Target.magnitude < 50)
{
point2Target.Normalize();
Flak flak = gameObject.AddComponent<Flak>();
flak.setPosition(go.transform.position);
point2Target.x = point2Target.x * -1;
point2Target.y = point2Target.y * -1;
flak.setVelocity(point2Target * 50);
break;
}
}*/
if (target != null)
{
var point2Target = (Vector2) go.transform.position - (Vector2) target.transform.position;
point2Target.Normalize();
float value = Vector3.Cross(point2Target, go.transform.right).z;
rb.angularVelocity = rotatingSpeed * value;
rb.velocity = go.transform.right * speed;
//Vector2 lastVel = rb.velocity;
//rb.AddForce(go.transform.right * speed;);
}
}
public void setPosition(int x, int y) { go.transform.position = new Vector3(x,y,11); }
private void OnCollisionEnter2D(Collision2D collision)
{
Debug.Log("hit");
Destroy (go, 0.02f);
}
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log("hit");
Destroy (go, 0.02f);
}
}
and finally the invoking
if (Input.GetKeyUp("i"))
{
var ship = gameObject.AddComponent<Ship>();
ship.setPosition((int)currFramePosition.x, (int)currFramePosition.y);
}
if (Input.GetKeyUp("v"))
{
var missile = gameObject.AddComponent<Missile>();
missile.setPosition((int)currFramePosition.x, (int)currFramePosition.y);
Debug.Log(missile);
}
Some help would be appreciated, thanks.
Related
I'm try to make Basketball hoops, I can throw ball one time, I reset game but I can not throw ball again , I don't like to reset scene.
GameController is a empty object [Manager] and below script attach to it.
GameController.cs:
public PlayerArcade player;
public float restartTime = 5f;
public static bool ResetBall = false;
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
void Update()
{
if(player.HoldingBall == false)
{
restartTime -= Time.deltaTime;
if (restartTime <= 0)
{
//SceneManager.LoadScene("Intro");
ResetBall = true;
restartTime = 5f;
}
// ResetBall = true;
}
}
My main player script as PlayerArcade.cs:
public GameObject Ball;
public Ball ball;
Rigidbody ballrb;
public GameObject PlayerCamera;
public float BallDistance = 1f;
public float ThrowPowerStrong = 550f;
public float ThrowPowerWeak = 350f;
public bool HoldingBall = true;
void Start()
{
ballrb = Ball.GetComponent<Rigidbody>();
ballrb.useGravity = false;
}
private void Awake()
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
void Update()
{
if (GameController.ResetBall == true)
{
ballrb.constraints = RigidbodyConstraints.None;
Ball.transform.position = new Vector3(212.5f, 3.227f, 4.11f);
ballrb.velocity = Vector3.zero;
ballrb.angularVelocity = Vector3.zero;
ballrb.transform.eulerAngles = new Vector3(0f, 0f, 0f);
ballrb.useGravity = false;
HoldingBall = true;
}
if (HoldingBall)
{
Ball.transform.position = PlayerCamera.transform.position + PlayerCamera.transform.forward * BallDistance;
if (Input.GetKeyDown(KeyCode.Y))
{
Debug.Log(ThrowPowerStrong);
HoldingBall = false;
ballrb.useGravity = true;
ballrb.AddForce(PlayerCamera.transform.forward * ThrowPowerStrong);
}
if (Input.GetKeyUp(KeyCode.A))
{
HoldingBall = false;
ballrb.useGravity = true;
ballrb.AddForce(PlayerCamera.transform.forward * ThrowPowerWeak);
}
}
}
And Ball.cs is attached to my ball object:
public PlayerArcade player;
[SerializeField] Transform PlayerBall;
Rigidbody ballrb;
// Start is called before the first frame update
void Start()
{
ballrb = PlayerBall.GetComponent<Rigidbody>();
}
private void Awake()
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
when you throw the ball by pressing (A, or Y) just do
GameController.ResetBall = false; GameController.ResetBall = false;
Alright so basically the issue that I've been having is that for some reason a GameObject is interfering with the OnPointerEnter function. I'm pretty sure that OnPointerEnter detects only UI. So that's why I'm extremely confused when seeing that a specific GameObject in this case the PlayerLogic GameObject (which you can see in the screenshot) is for some reason interfering with the detection of UI elements. The reason I believe it is this specific GameObject is because once I do PlayerLogic.SetActive(false); OnPointerEnter starts to work again, and I'm also sure that it isn't any of the children of PlayerLogic because I've tried turning them off specifically and it still didn't work.
Inspector of the PlayerLogic object
Hierarchy
The code I'm using to test OnPointerEnter
After some testing I've realized that its the specific issue lies within the Player script on the PlayerLogic GameObject. Now what confuses me is that once I turn off the Player component OnPointer doesn't work, but if I were to remove the Player component completely from the PlayerLogic GameObject OnPointerEnter works.
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Collections;
using System.Collections.Generic;
public class Player : MonoBehaviour, TakeDamage {
[SerializeField] private Animator playerAnimator;
[SerializeField] private Transform mainCameraTransform;
private bool isRunning = false;
[SerializeField] private CharacterController controller;
public float speed = 10f;
[SerializeField] private float jumpForce = 3f;
[SerializeField] private float gravity = -10000.81f;
Vector3 velocity;
Vector3 desiredMoveDirection;
private float dashSpeed = 30f;
private float mouseX;
private float mouseY;
[SerializeField]
private Transform Target;
[SerializeField]
private Transform player;
private float turnSmoothVelocity;
private float time = 0f;
public bool playerIsAttacking = false;
[SerializeField] private Slider playerHealth, playerMana;
[SerializeField] private TextMeshProUGUI healthText, manaText;
private Vector3 originalSpawnPos;
private bool playerIsDead = false;
[SerializeField] private LayerMask enemyLayerMask;
[SerializeField] private Transform playerLook;
private ShowHPBar obj;
private bool HPBarShown = false;
private bool unshowingHPBar = false;
public bool lookingAtEnemy = false;
public RaycastHit hit;
[SerializeField] private Canvas abilityCanvas;
[SerializeField] private Slider CD1;
[SerializeField] private Slider CD2;
[SerializeField] private Slider CD3;
public List<Ability> currentlyEquippedAbilites = new List<Ability>();
public List<string> abilityTexts = new List<string>();
public float[] abilityCooldowns = new float[3];
private float manaRegenTime;
//public List<Image> abilityImages = new List<Image>();
private void Awake() {
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
}
private void Start() {
playerHealth.onValueChanged.AddListener(delegate {OnValueChangedHealth(); });
playerMana.onValueChanged.AddListener(delegate {OnValueChangedMana(); });
originalSpawnPos = transform.position;
}
private void Update() {
if (!playerIsDead) {
PlayerMovementAndRotation();
}
PlayerDash();
PlayerRun();
PlayerSeeEnemyHealth();
PlayerActivateAbility();
if (manaRegenTime > 0.5f) {
playerMana.value += playerMana.maxValue/100;
manaRegenTime = 0;
}
playerLook.rotation = mainCameraTransform.rotation;
time += Time.deltaTime;
manaRegenTime += Time.deltaTime;
#region Ability Cooldowns
if (currentlyEquippedAbilites.Count > 0) {
if (currentlyEquippedAbilites[0].cooldown <= abilityCooldowns[0])
{
currentlyEquippedAbilites[0].isOnCooldown = false;
abilityCooldowns[0] = 0;
CD1.value = 0;
}
else if (currentlyEquippedAbilites[0].isOnCooldown) {
abilityCooldowns[0] += Time.deltaTime;
CD1.value = currentlyEquippedAbilites[0].cooldown - abilityCooldowns[0];
}
}
if (currentlyEquippedAbilites.Count > 1) {
if (currentlyEquippedAbilites[1].cooldown <= abilityCooldowns[1])
{
currentlyEquippedAbilites[1].isOnCooldown = false;
abilityCooldowns[1] = 0;
CD2.value = 0;
}
else if (currentlyEquippedAbilites[1].isOnCooldown) {
abilityCooldowns[1] += Time.deltaTime;
CD2.value = currentlyEquippedAbilites[1].cooldown - abilityCooldowns[1];
}
}
if (currentlyEquippedAbilites.Count > 2) {
if (currentlyEquippedAbilites[2].cooldown <= abilityCooldowns[2])
{
currentlyEquippedAbilites[2].isOnCooldown = false;
abilityCooldowns[2] = 0;
CD3.value = 0;
}
else if (currentlyEquippedAbilites[2].isOnCooldown) {
abilityCooldowns[2] += Time.deltaTime;
CD3.value = currentlyEquippedAbilites[2].cooldown - abilityCooldowns[2];
}
}
#endregion
}
private void PlayerRun() {
if (Input.GetKey(KeybindsScript.RunKey) && (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0)) {
playerAnimator.SetInteger("isRunning", 1);
playerAnimator.SetInteger("isIdle", 0);
playerAnimator.SetInteger("isWalking", 0);
speed = 15f;
}
else if (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0) {
playerAnimator.SetInteger("isWalking", 1);
playerAnimator.SetInteger("isIdle", 0);
playerAnimator.SetInteger("isRunning", 0);
speed = 10f;
}
else {
playerAnimator.SetInteger("isRunning", 0);
playerAnimator.SetInteger("isWalking", 0);
playerAnimator.SetInteger("isIdle", 1);
speed = 10f;
}
}
private void PlayerMovementAndRotation() {
bool isGrounded = controller.isGrounded;
if (isGrounded && velocity.y < 0) {
velocity.y = -2f;
}
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
Vector3 moveDir = (transform.right*horizontal+transform.forward*vertical).normalized;
controller.Move(moveDir*Time.deltaTime*speed);
transform.eulerAngles = new Vector3(0f, mainCameraTransform.eulerAngles.y, 0f);
if (Input.GetKeyDown(KeybindsScript.JumpKey) && isGrounded) {
velocity.y = Mathf.Sqrt(jumpForce * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
private void PlayerDash() {
if (Input.GetKeyDown(KeybindsScript.DashKeybind) && isRunning == false) {
if (Input.GetKey(KeybindsScript.MovementKeyBackward)) {
StartCoroutine(PlayerDashTiming(2));
}
else if (Input.GetKey(KeybindsScript.MovementKeyRight)) {
StartCoroutine(PlayerDashTiming(3));
}
else if (Input.GetKey(KeybindsScript.MovementKeyLeft)) {
StartCoroutine(PlayerDashTiming(4));
}
else {
StartCoroutine(PlayerDashTiming(1));
}
}
}
private void PlayerSeeEnemyHealth() {
if (Physics.Raycast(playerLook.position, playerLook.forward, out hit, 1000f, enemyLayerMask)) {
obj = hit.transform.gameObject.GetComponent<ShowHPBar>();
if (obj != null && !HPBarShown && !unshowingHPBar) {obj.ShowHPBarFunction(); HPBarShown = true;}
lookingAtEnemy = true;
}
else {
if (obj != null && HPBarShown) {StartCoroutine(UnShowHPBar(obj)); HPBarShown = false;}
}
}
public void PlayerEquipAbility(Ability ability, int place) {
if (currentlyEquippedAbilites.Count < place) {currentlyEquippedAbilites.Add(ability);}
else {currentlyEquippedAbilites[place-1] = ability;}
//if (abilityImages.Count < place) {abilityImages.Add(ability.icon);}
//else {abilityImages.Add(ability.icon);}
if (abilityTexts.Count < place) {abilityTexts.Add(ability.name);}
else {abilityTexts[place-1] = ability.name;}
for (int i=0;i < abilityTexts.Count;++i) {
abilityCanvas.transform.GetChild(i).GetChild(0).GetComponent<TextMeshProUGUI>().text = abilityTexts[i];
abilityCanvas.transform.GetChild(i).GetChild(1).GetComponent<Slider>().maxValue = ability.cooldown;
}
}
private void PlayerActivateAbility() {
if (Input.GetKeyDown(KeyCode.Alpha1)) {
if (currentlyEquippedAbilites[0] != null) {
if (currentlyEquippedAbilites[0].manaCost <= playerMana.value && !currentlyEquippedAbilites[0].isOnCooldown) {
ParticleEffect pe = currentlyEquippedAbilites[0].script.gameObject.GetComponent<ParticleEffect>();
playerMana.value -= currentlyEquippedAbilites[0].manaCost;
currentlyEquippedAbilites[0].isOnCooldown = true;
if (pe != null) {pe.PlayAnimation();}
}
}
}
}
public void OnValueChangedHealth() {
healthText.text = playerHealth.value + "/" + PlayerStats.HealthPoints;
}
public void OnValueChangedMana() {
manaText.text = playerMana.value + "/" + PlayerStats.ManaAmount;
}
public void TakeDamageFunction(float damage) {
playerHealth.value -= damage;
if (playerHealth.value <= 0) {
StartCoroutine(PlayerDeath());
}
}
IEnumerator PlayerDashTiming(int x) {
isRunning = true;
float time = 0f;
Vector3 savedVector = Vector3.zero;
switch (x) {
case 1:
savedVector = transform.forward;
break;
case 2:
savedVector = -transform.forward;
break;
case 3:
savedVector = transform.right;
break;
case 4:
savedVector = -transform.right;
break;
}
while(time < .3f)
{
time += Time.deltaTime;
controller.Move(savedVector * dashSpeed * Time.deltaTime);
yield return null;
}
yield return new WaitForSeconds(1.5f);
isRunning = false;
}
IEnumerator PlayerDeath() {
//Respawn
playerIsDead = true;
playerAnimator.enabled = false;
yield return new WaitForSeconds(1f);
playerHealth.value = 100;
transform.position = originalSpawnPos;
yield return new WaitForSeconds(0.1f);
playerIsDead = false;
playerAnimator.enabled = true;
}
IEnumerator UnShowHPBar(ShowHPBar obj) {
unshowingHPBar = true;
yield return new WaitForSeconds(1.5f);
obj.ShowHPBarFunction();
unshowingHPBar = false;
}
}
This is the Player.cs script.
I'm pretty sure that OnPointerEnter detects only UI.
No.
It works "out of the box" on UI because by default every Canvas contains a GraphicsRaycaster component which is then used and handled by the EventSystem.
For non-UI 3D objects you have to make sure
your objects have 3D Colliders
the Colliders are on the same object as the IPointerXY interfaces
on your Camera there is a PhysicsRayster component
For non-UI 2D objects quite similar
your objects have a 2D Collider
the colliders are on the same object as the IPointerXY interfaces
the Camera has a Physics2DRaycaster component
Note that it is possible that any other collider or in general raycast blocking object is between your input and the target object which would also prevent the OnPointerXY to be triggered on your objects.
The CharacterController
is simply a capsule shaped Collider
which can be told to move in some direction from a script.
which is probably blocking the input.
Now with your Player code:
You do
Cursor.lockState = CursorLockMode.Locked;
in Awake so even if you turn it off afterwards this already took effect.
Im trying to write a script where the audio source plays an audioclip array with 4 sounds in it. The sounds are gonna be played faster and louder when my character is sprinting and quieter and slower when my character is crouching. My problem is that the audiosource doesn't play the audioclip. I've checked it multiple times and I really can't find the problem.
`public class PlayerFootsteps : MonoBehaviour
{
private AudioSource footstepSound;
[SerializeField]
private AudioClip[] footstepClip;
private CharacterController charController;
[HideInInspector]
public float VolumeMin, VolumeMax;
private float accumulatedDistance;
[HideInInspector]
public float stepDistance;
void Awake()
{
footstepSound = GetComponent<AudioSource>();
charController = GetComponentInParent<CharacterController>();
}
void Update()
{
CheckToPlayFootstepSounds();
}
void CheckToPlayFootstepSounds()
{
if (!charController.isGrounded)
{
return;
}
if (charController.velocity.magnitude > 0)
{
accumulatedDistance += Time.deltaTime;
if (accumulatedDistance > stepDistance)
{
footstepSound.volume = Random.Range(VolumeMin, VolumeMax);
footstepSound.clip = footstepClip[Random.Range(0, footstepClip.Length)];
footstepSound.Play();
accumulatedDistance = 0f;
}
else
{
accumulatedDistance = 0f;
}
}
}
}`
public class PlayerSprintAndCrouch : MonoBehaviour
{
private PlayerMovement playerMovement;
public float sprintSpeed = 10f, moveSpeed = 5f, crouchSpeed = 2f;
[SerializeField]
private Transform lookRoot;
private float standHeight = 1.6f, crouchHeight = 1f;
private bool isCrouching;
private PlayerFootsteps playerFootsteps;
private float sprintVolume = 1f;
private float crouchVolume = 0.1f;
private float walkVolumeMin = 0.2f, walkVolumeMax = 0.6f;
private float walkStepDistance = 0.4f, sprintStepDistance = 0.25f, crouchStepDistance = 0.5f;
void Awake()
{
playerMovement = GetComponent<PlayerMovement>();
playerFootsteps = GetComponentInChildren<PlayerFootsteps>();
}
void Start()
{
playerFootsteps.VolumeMin = walkVolumeMin;
playerFootsteps.VolumeMax = walkVolumeMax;
playerFootsteps.stepDistance = walkStepDistance;
}
// Update is called once per frame
void Update()
{
Sprint();
Crouch();
}
void Sprint()
{
if (Input.GetKeyDown(KeyCode.LeftShift) && !isCrouching)
{
playerMovement.speed = sprintSpeed;
playerFootsteps.stepDistance = sprintStepDistance;
playerFootsteps.VolumeMin = sprintVolume;
playerFootsteps.VolumeMax = sprintVolume;
}
if (Input.GetKeyUp(KeyCode.LeftShift) && !isCrouching)
{
playerMovement.speed = moveSpeed;
playerFootsteps.stepDistance = walkStepDistance;
playerFootsteps.VolumeMin = walkVolumeMin;
playerFootsteps.VolumeMax = walkVolumeMax;
}
}
void Crouch()
{
if (Input.GetKeyDown(KeyCode.LeftControl))
{
if (isCrouching)
{
lookRoot.localPosition = new Vector3(0f, standHeight, 0f);
playerMovement.speed = moveSpeed;
isCrouching = false;
}
else
{
lookRoot.localPosition = new Vector3(0f, crouchHeight, 0f);
playerMovement.speed = crouchSpeed;
playerFootsteps.stepDistance = crouchStepDistance;
playerFootsteps.VolumeMin = crouchVolume;
playerFootsteps.VolumeMax = crouchVolume;
isCrouching = true;
}
}
}
}
The problem is that you are setting the accumulatedDistance to 0, This should fix your problem:
void CheckToPlayFootstepSounds()
{
if (!charController.isGrounded)
{
return;
}
if (charController.velocity.magnitude > 0)
{
accumulatedDistance += Time.deltaTime;
if (accumulatedDistance > stepDistance)
{
footstepSound.volume = Random.Range(VolumeMin, VolumeMax);
footstepSound.clip = footstepClip[Random.Range(0, footstepClip.Length)];
footstepSound.Play();
accumulatedDistance = 0f;
}
else
{
// accumulatedDistance = 0f; Remove This
}
}
}
I am doing a project in Unity with C# and I want to have two drones that will wander in the room, and then attack each other using a state machine.
I have three classes AttackState, ChaseState and WonderState
For example, this is my WanderState Class:
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Linq;
using System;
using UnityEngine;
public class WanderState : BaseState
{
private Vector3? _destination;
private float stopDistance = 1.5f;
private float turnSpeed = 1f;
private readonly LayerMask _layerMask = LayerMask.NameToLayer("Walls");
private float _rayDistance = 5.0f;
private Quaternion _desiredRotation;
private Vector3 _direction;
private Drone _drone;
public WanderState(Drone drone) : base(drone.gameObject)
{
_drone = drone;
}
public override Type Tick()
{
var chaseTarget = CheckForAggro();
if (chaseTarget != null)
{
_drone.SetTarget(chaseTarget);
return typeof(ChaseState);
}
if (_destination.HasValue == false || Vector3.Distance(transform.position, _destination.Value) <= stopDistance)
{
FindRandomDestination();
}
transform.rotation = Quaternion.Slerp(transform.rotation, _desiredRotation, Time.deltaTime * turnSpeed); //Time.deltaTime * turnSpeed
if (IsForwardBlocked()) //IsForwardBlocked()
{
transform.rotation = Quaternion.Lerp(transform.rotation, _desiredRotation, 0.2f);
}
else
{
float droneSpeed = 2f;
transform.Translate(Vector3.forward * Time.deltaTime * droneSpeed);
}
Debug.DrawRay(transform.position, _direction * _rayDistance, Color.red);
while (IsPathBlocked())
{
FindRandomDestination();
Debug.Log("Wall");
}
return null;
}
private bool IsForwardBlocked()
{
Ray ray = new Ray(transform.position, transform.forward);
return Physics.SphereCast(ray, 0.5f, _rayDistance, _layerMask);
}
private bool IsPathBlocked()
{
Rigidbody obj = new Rigidbody();
Ray ray = new Ray(transform.position, _direction);
return Physics.SphereCast(ray, 0.5f, _rayDistance, _layerMask);
}
private void FindRandomDestination()
{
Vector3 testPosition = (transform.position + (transform.forward * 4f)) + new Vector3(UnityEngine.Random.Range(-4.5f, 4.5f), 0f,UnityEngine.Random.Range(-4.5f, 4.5f));
_destination = new Vector3(testPosition.x, 1f, testPosition.z);
_direction = Vector3.Normalize(_destination.Value - transform.position);
_direction = new Vector3(_direction.x, 0f, _direction.z);
_desiredRotation = Quaternion.LookRotation(_direction);
Debug.Log("Got direction");
}
Quaternion startingAngle = Quaternion.AngleAxis(-60, Vector3.up);
Quaternion stepAngle = Quaternion.AngleAxis(5, Vector3.up);
private Transform CheckForAggro()
{
float aggroRadius = 5f;
RaycastHit hit;
var angle = transform.rotation * startingAngle;
var direction = angle * Vector3.forward;
var pos = transform.position;
for (var i = 0; i < 24; i++)
{
if (Physics.Raycast(pos, direction, out hit, aggroRadius))
{
var drone = hit.collider.GetComponent<Drone>();
if (drone != null && drone.Team1 != gameObject.GetComponent<Drone>().Team1)
{
Debug.DrawRay(pos, direction * hit.distance, Color.red);
return drone.transform;
}
else
{
Debug.DrawRay(pos, direction * hit.distance, Color.yellow);
}
}
else
{
Debug.DrawRay(pos, direction * aggroRadius, Color.white);
}
direction = stepAngle * direction;
}
return null;
}
}
Then I have 2 drones, and each of them have a Drone script and a StateMachine script as follows:
public class Drone : MonoBehaviour
{
[SerializeField] private Team _team;
[SerializeField] private GameObject _laserVisual;
public Transform Target { get; private set; }
public Team Team1=> _team;
public StateMachine StateMachine => GetComponent<StateMachine>();
private void Awake()
{
InitializeStateMachine();
}
private void InitializeStateMachine()
{
var states = new Dictionary<Type, BaseState>()
{
{typeof(WanderState), new WanderState(this) },
{typeof(ChaseState), new ChaseState(this) },
{typeof(AttackState), new AttackState(this) }
};
GetComponent<StateMachine>().SetStates(states);
}
public void SetTarget(Transform target)
{
Target = Target;
}
public void FireWeapon()
{
_laserVisual.transform.position = (Target.position + transform.position) / 2f;
float distance = Vector3.Distance(a: Target.position, b: transform.position);
_laserVisual.transform.localScale = new Vector3(0.1f, 0.1f, distance);
_laserVisual.SetActive(true);
StartCoroutine(TurnOffLaser());
}
public IEnumerator TurnOffLaser()
{
yield return new WaitForSeconds(0.25f);
_laserVisual.SetActive(false);
if (Target != null)
{
GameObject.Destroy(Target.gameObject);
}
}
public enum Team
{
Red,
Blue
}
public class StateMachine : MonoBehaviour
{
private Dictionary<Type, BaseState> _availableStates;
public BaseState CurrentState { get; private set; }
public event Action<BaseState> OnStateChanged;
public void SetStates(Dictionary<Type, BaseState> states)
{
_availableStates = states;
}
private void Update()
{
if(CurrentState == null)
{
CurrentState = _availableStates.Values.First();
}
var nextState = CurrentState?.Tick();
if (nextState != null && nextState != CurrentState.GetType())
{
SwitchToNewState(nextState);
}
}
public void SwitchToNewState(Type nextState)
{
CurrentState = _availableStates[nextState];
OnStateChanged?.Invoke(CurrentState);
}
}
The problem I am facing is that my drones are going through the room walls
I tried to set for the walls a Mesh Collider or a Box collider, but none of these options worked. Also, for the drones I have a sphere collider.
Does anyone know why this behaviour and what can I do to fix it?
Add a rigidbody to the drone and make sure isKinematic is unchecked.
Like the title says, the enemy projectiles are not launching. They are spawned and destroyed in the same place. They do not fire toward the target. Code in link:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MonkeyController : MonoBehaviour {
private const int MAX_INJURES = 1;
public float DurationMovement = 2f;
public Transform SpawnLocation;
public Transform[] PatrolPoints;
public GameObject MonkeyProjectile;
public Rigidbody2D Abby;
public float AttackDelay = 0.75f;
public float ProjectileSpeed = 1;
public int ProjectilesCount = 4;
public float activePosition;
public float passivePosition;
private List<GameObject> ProjectileList = new List<GameObject>();
private int PatrolIndex = 0;
private int injures = 0;
private bool canPatrol;
private Coroutine fireCoroutine;
private Coroutine patrolCoroutine;
private Coroutine movementCoroutine;
WaitForSeconds delay;
Vector2 AttackVector = Vector2.zero;
// Use this for initialization
private void Start () {
delay = new WaitForSeconds(AttackDelay);
InitializeProjectileList();
fireCoroutine = StartCoroutine(MonkeyFireProjectileBehaviour());
patrolCoroutine = StartCoroutine(PatrolBehaviour(PatrolPoints[PatrolIndex].position));
}
private IEnumerator MonkeyFireProjectileBehaviour()
{
yield return delay;
if (GameManager.GetInstance().gameState == GameState.GAME_OVER)
yield return null;
AttackVector = Abby.transform.position - (transform.position /*+ (Vector3)Abby.velocity/10f*/);
FireProjectile(AttackVector);
fireCoroutine = StartCoroutine(MonkeyFireProjectileBehaviour());
}
private IEnumerator PatrolBehaviour(Vector3 animationLocation)
{
canPatrol = true;
float distance = (transform.position - animationLocation).magnitude;
float duration = DurationMovement;
Vector3 startingPos = transform.position;
float t = 0;
while (t < 1 && canPatrol)
{
t += Time.deltaTime / duration;
transform.position = Vector3.Lerp(startingPos, animationLocation, t);
yield return null;
}
if (!canPatrol)
yield break;
transform.position = animationLocation;
IncrementMovementIndex();
patrolCoroutine = StartCoroutine(PatrolBehaviour(PatrolPoints[PatrolIndex].position));
yield return null;
}
private void IncrementMovementIndex()
{
PatrolIndex++;
if(PatrolIndex == PatrolPoints.Length)
{
PatrolIndex = 0;
}
}
private void InitializeProjectileList()
{
GameObject Projectile;
for (int i = 0; i < ProjectilesCount; i++)
{
Projectile = Instantiate(MonkeyProjectile);
Projectile.SetActive(false);
ProjectileList.Add(Projectile);
}
}
private void FireProjectile(Vector2 forceProjectile)
{
foreach (GameObject projectile in ProjectileList)
{
if (!projectile.activeInHierarchy)
{
projectile.transform.position = SpawnLocation.position;
projectile.SetActive(true);
projectile.GetComponent<TrailRenderer>().enabled = true;
projectile.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Dynamic;
projectile.GetComponent<Rigidbody2D>().AddForce(forceProjectile * (ProjectileSpeed + Random.Range(0, ProjectileSpeed/2)), ForceMode2D.Impulse);
break;
}
}
}
private IEnumerator DoMovementCoroutine()
{
yield return new WaitForSeconds (0.01F);
transform.localPosition = new Vector2(passivePosition, 0);
yield return AnimatorExecutive.AnimatePositionCoroutine (gameObject, new Vector2 (activePosition, 0), 5.0F);
fireCoroutine = StartCoroutine(MonkeyFireProjectileBehaviour());
patrolCoroutine = StartCoroutine(PatrolBehaviour(PatrolPoints[PatrolIndex].position));
}
private void OnCollisionEnter2D(Collision2D otherCollision)
{
if (otherCollision.gameObject.tag == "Projectile")
{
injures++;
if (injures >= MAX_INJURES)
{
injures = 0;
canPatrol = false;
GetComponent<AudioSource>().Play();
if(fireCoroutine != null) StopCoroutine (fireCoroutine);
if(patrolCoroutine != null) StopCoroutine (patrolCoroutine);
movementCoroutine = StartCoroutine (DoMovementCoroutine());
}
}
}
}
With the information your provided, I would say the problem you may be facing is the GameObject you pass in the inspector to get the SpawnLocation has got a collider and a script with a OnCollisionEnter2D, which detect the projectil when you instantiate it and destroy it.
However, you are not destroying the projectil inside this OnCollisionEnter2D.
private void OnCollisionEnter2D(Collision2D otherCollision)
{
if (otherCollision.gameObject.tag == "Projectile")
{
injures++;
if (injures >= MAX_INJURES)
{
injures = 0;
canPatrol = false;
GetComponent<AudioSource>().Play();
if(fireCoroutine != null) StopCoroutine (fireCoroutine);
if(patrolCoroutine != null) StopCoroutine (patrolCoroutine);
movementCoroutine = StartCoroutine (DoMovementCoroutine());
}
}
}
In the case you dont have in your code any line to destroy the projectil gameobject after a collision. The problem could be you are not reaching this line projectile.SetActive(true);
I will try to replicate your code and check what may be happening