using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class ClickToMove : MonoBehaviour
{
[Header("Stats")]
public float attackDistance;
public float attackRate;
private float nextAttack;
private NavMeshAgent navMeshAgent;
private Animator anim;
private Transform targetedEnemy;
private bool enemyClicked;
private bool walking;
void Awake()
{
anim = GetComponent<Animator>();
navMeshAgent = GetComponent<NavMeshAgent>();
}
// Update is called once per frame
void Update()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Input.GetButtonDown("Fire2"))
{
if (Physics.Raycast(ray, out hit,1000))
{
if (hit.collider.tag == "Enemy")
{
targetedEnemy = hit.transform;
enemyClicked = true;
print("Nailed em");
}
else
{
walking = true;
enemyClicked = false;
navMeshAgent.isStopped = false;
navMeshAgent.destination = hit.point;
}
}
}
if (enemyClicked)
{
MoveAndAttack();
}
--> if (navMeshAgent.remaingDistance <= navMeshAgent.stoppingDistance)
{
walking = false;
}
else
{
walking = true;
}
//anim.SetBool("isWalking", walking);
}
void MoveAndAttack()
{
if (targetedEnemy == null)
{
return;
}
navMeshAgent.destination = targetedEnemy.position;
if (navMeshAgent.remainingDistance > attackDistance)
{
navMeshAgent.isStopped = false;
walking = true;
}
else
{
transform.LookAt(targetedEnemy);
Vector3 dirToAttack = targetedEnemy.transform.position - transform.position;
if (Time.time > nextAttack)
{
nextAttack = Time.time + attackRate;
}
}
navMeshAgent.isStopped = true;
walking = false;
}
}
The line of code with --> is my main problem. I am new to unity and coding, so yes feel free to school me please.
'NavMeshAgent' does not contain a definition for 'remaingDistance' and no accessible extension method 'remaingDistance' accepting a first argument of type 'NavMeshAgent' could be found (are you missing a using directive or an assembly reference?).
I understand the console tells me the problem, I just have no idea how to fix it.
Related
I have another issue with my animator in 2D.
Currently i have only few slopes in game, but it annoys me, because i don't know how to make animation work properly on them. This is one example:
As you can see, there is little slope. Now how my Animator looks like:
The code now looks like it:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using System;
public class PlayerMovementScript : MonoBehaviour
{
[SerializeField] float runSpeed;
[SerializeField] float jumpSpeed;
[SerializeField] float climbSpeed;
Vector2 moveInput;
Rigidbody2D playerRigidbody;
Animator playerAnimator;
CapsuleCollider2D playerCapsuleCollider;
float gravityScaleAtStart;
void Start()
{
playerRigidbody = GetComponent<Rigidbody2D>();
playerAnimator = GetComponent<Animator>();
playerCapsuleCollider = GetComponent<CapsuleCollider2D>();
gravityScaleAtStart = playerRigidbody.gravityScale;
}
void Update()
{
Run();
FlipSprite();
ClimbLadder();
Falling();
}
void OnMove(InputValue value)
{
moveInput = value.Get<Vector2>();
Debug.Log(moveInput);
}
void OnJump(InputValue value)
{
if (!playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Ground"))) { return; }
if (value.isPressed)
{
playerRigidbody.velocity += new Vector2(0f, jumpSpeed);
}
}
void Run()
{
Vector2 runVelocity = new Vector2(moveInput.x * runSpeed, playerRigidbody.velocity.y);
playerRigidbody.velocity = runVelocity;
bool playerHasHorizontalSpeed = Math.Abs(playerRigidbody.velocity.x) > Mathf.Epsilon;
if (playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Ground")))
{
playerAnimator.SetBool("isRunning", playerHasHorizontalSpeed);
} else
{
playerAnimator.SetBool("isRunning", false);
}
}
void FlipSprite()
{
bool playerHasHorizontalSpeed = Math.Abs(playerRigidbody.velocity.x) > Mathf.Epsilon;
if (playerHasHorizontalSpeed)
{
transform.localScale = new Vector2(Mathf.Sign(playerRigidbody.velocity.x), 1f);
}
}
void ClimbLadder()
{
if (!playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Climb"))) {
playerRigidbody.gravityScale = gravityScaleAtStart;
playerAnimator.SetBool("isClimbing", false);
playerAnimator.SetBool("isClimbingIdle", false);
return;
}
Vector2 climbVelocity = new Vector2(playerRigidbody.velocity.x, moveInput.y * climbSpeed);
playerRigidbody.velocity = climbVelocity;
playerRigidbody.gravityScale = 0;
bool playerHasVerticalSpeed = Math.Abs(playerRigidbody.velocity.y) > Mathf.Epsilon;
playerAnimator.SetBool("isClimbing", playerHasVerticalSpeed);
playerAnimator.SetBool("isClimbingIdle", !playerHasVerticalSpeed);
}
void Falling()
{
if (
playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Climb"))
|| playerCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Ground"))
) {
playerAnimator.SetBool("isJumping", false);
playerAnimator.SetBool("isLanding", false);
return;
}
bool playerHasVerticalSpeed = Math.Abs(playerRigidbody.velocity.y) > Mathf.Epsilon;
if (playerRigidbody.velocity.y >= 0)
{
playerAnimator.SetBool("isJumping", playerHasVerticalSpeed);
playerAnimator.SetBool("isLanding", false);
} else
{
playerAnimator.SetBool("isJumping", false);
playerAnimator.SetBool("isLanding", playerHasVerticalSpeed);
}
}
}
If my player went on slope, Animator shows my animations switch quickly between Run, Jump and Land. How to fix it to save correct jump animation?
I have a Unity project that I started a couple of days ago. It is a simple 2D top down shooting game, which is aimed to be played on smartphone platforms.
I have a Shooting script, which basically has a method called Shoot1, which spawns in a bullet.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Shooting : MonoBehaviour
{
public Transform firePoint;
public GameObject BulletRedPrefab;
public GameObject BulletGreenPrefab;
public float bulletForce = 20f;
// Update is called once per frame
void Start()
{
}
void Update()
{
}
public IEnumerator Shoot1()
{
yield return new WaitForSeconds(0.00001f);
GameObject bullet = Instantiate(BulletRedPrefab, firePoint.position, firePoint.rotation);
Rigidbody2D rb = bullet.GetComponent<Rigidbody2D>();
rb.AddForce(firePoint.up * bulletForce, ForceMode2D.Impulse);
}
}
I also have the Swipe script which determines the direction of the swipe, etc.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Swipe : MonoBehaviour
{
private bool tap, swipeUp, swipeDown, swipeLeft, swipeRight;
private bool isDraging = false;
private Vector2 startTouch, swipeDelta;
// Update is called once per frame
private void Update()
{
tap = swipeUp = swipeDown = swipeLeft = swipeRight = false;
if (Input.touches.Length > 0)
{
if (Input.touches[0].phase == TouchPhase.Began)
{
isDraging = true;
tap = true;
startTouch = Input.touches[0].position;
}
else if (Input.touches[0].phase == TouchPhase.Ended || Input.touches[0].phase == TouchPhase.Canceled)
{
isDraging = false;
Reset();
}
}
if (Input.GetMouseButtonDown(0))
{
tap = true;
isDraging = true;
startTouch = Input.mousePosition;
}
else if (Input.GetMouseButtonUp(0))
{
isDraging = false;
Reset();
}
swipeDelta = Vector2.zero;
if (isDraging)
{
if (Input.touches.Length > 0)
swipeDelta = Input.touches[0].position - startTouch;
else if (Input.GetMouseButton(0))
swipeDelta = (Vector2)Input.mousePosition - startTouch;
}
if (swipeDelta.magnitude > 125)
{
float x = swipeDelta.x;
float y = swipeDelta.y;
if (Mathf.Abs(x) > Mathf.Abs(y))
{
if (x < 0)
swipeLeft = true;
else
swipeRight = true;
}
else
{
if (y < 0)
swipeDown = true;
else
swipeUp = true;
}
Reset();
}
}
private void Reset()
{
startTouch = swipeDelta = Vector2.zero;
isDraging = false;
}
public Vector2 SwipeDelta { get { return swipeDelta; } }
public bool SwipeUp { get { return swipeUp; } }
public bool SwipeDown { get { return swipeDown; } }
public bool SwipeLeft { get { return swipeLeft; } }
public bool SwipeRight { get { return swipeRight; } }
}
And I have the GestureDetector script which is aimed to shoot a bullet whenever the user swipes left, right, up or down. When I tried to make the player object (which is called robot) move via swiping, it worked. But when I try calling a method from another class with swiping, it's not working.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GestrueDetector : MonoBehaviour
{
public Shooting other;
public Swipe swipeControls;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
private void Update()
{
if (GameObject.Find("robot") != null)
{
if (swipeControls.SwipeLeft)
desirePosition += Vector3.left;
other.Shoot1();
if (swipeControls.SwipeRight)
desirePosition += Vector3.right;
other.Shoot1();
if (swipeControls.SwipeUp)
desirePosition += Vector3.up;
other.Shoot1();
if (swipeControls.SwipeDown)
desirePosition += Vector3.down;
other.Shoot1();
}
}
}
I just started using unity this week, so I'm quite new to the software. Thank you very much!
For coroutines you need to call this methods like this:
StartCoroutine(Shoot1());
I a little bit changed your classes:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Shooting : MonoBehaviour
{
public Transform firePoint;
public GameObject BulletRedPrefab;
public GameObject BulletGreenPrefab;
public float bulletForce = 20f;
void Start ()
{
}
void Update()
{
}
public void Shoot()
{
StartCoroutine(Shoot1());
}
private IEnumerator Shoot1()
{
yield return new WaitForSeconds(0.00001f);
GameObject bullet = Instantiate(BulletRedPrefab, firePoint.position, firePoint.rotation);
Rigidbody2D rb = bullet.GetComponent<Rigidbody2D>();
rb.AddForce(firePoint.up * bulletForce, ForceMode2D.Impulse);
}
}
And for GestrueDetector:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GestrueDetector : MonoBehaviour
{
public Shooting other;
public Swipe swipeControls;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
private void Update()
{
if (GameObject.Find("robot") != null)
{
if (swipeControls.SwipeLeft)
desirePosition += Vector3.left;
other.Shoot();
if (swipeControls.SwipeRight)
desirePosition += Vector3.right;
other.Shoot();
if (swipeControls.SwipeUp)
desirePosition += Vector3.up;
other.Shoot();
if (swipeControls.SwipeDown)
desirePosition += Vector3.down;
other.Shoot();
}
}
}
Just read more about how coroutines are working in Unity - https://docs.unity3d.com/ScriptReference/Coroutine.html
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using Whilefun.FPEKit;
public class RoboSphereWindowBreakInteraction : MonoBehaviour
{
public Transform target;
public InteractableObjects interactableObjects;
public AudioClip audioClip;
public float speed;
private bool hasStarted = false;
private Animator anim;
void Update()
{
if ((Input.GetKeyDown(KeyCode.B) || (hasStarted == true)))
{
float step = speed * Time.deltaTime; // calculate distance to move
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
hasStarted = true;
}
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.name == "Square 1")
{
GetComponent<Rigidbody>().isKinematic = false;
hasStarted = false;
Destroy(GameObject.Find("Wall_Window_Long_03"));
}
}
public void ActivateRoboSphere()
{
foreach(Transform child in transform)
{
if(child.name == "Camera")
{
RepositionCamera(child);
}
}
anim = GetComponent<Animator>();
anim.enabled = true;
if (!anim.GetBool("Open_Anim"))
{
anim.SetBool("Open_Anim", true);
StartCoroutine(PlayAudio());
}
else
{
//anim.SetBool("Open_Anim", false);
}
}
private void RepositionCamera(Transform camera)
{
var Eyes = GameObject.Find("eyeDome");
camera.position = Eyes.transform.position + Eyes.transform.forward;
camera.LookAt(Eyes.transform);
camera.GetComponent<Camera>().enabled = true;
}
IEnumerator PlayAudio()
{
AudioSource audio = GetComponent<AudioSource>();
audio.Play();
yield return new WaitForSeconds(audio.clip.length);
audio.clip = audioClip;
audio.Play();
}
}
It's getting inside the PlayAudio but the sound is not heard.
The audio source component screenshot settings :
The only problem I see with this code is that initially, your audio source's clip isn't set to anything. Thus will result in a null ref exception on this line:
yield return new WaitForSeconds(audio.clip.length);
Add a null check and you should be good to go
if (audioSource.clip != null)
{
yield return new WaitForSeconds(audioSource.clip.length);
}
I'm creating a FPS game and I have the following issue:
Sometimes, when I shoot at the enemies the hit is not recognized, even if the player is shooting in front of them. However, when they attack the player, the hit is recognized normally.
They have a box collider and a rigidbody attached to them.
This script is attached to the player:
using System.Collections.Generic;
using UnityEngine;
public class DisparaArma : MonoBehaviour
{
private GerenciaArma gerenciaArma;
public float nDisparo = 15f;
private float TempoProximoDisparo;
public float damage = 20f;
private Animator ZoomCameraIn;
private bool zoomed;
private Camera Maincamera;
private GameObject mira;
// Start is called before the first frame update
void Start()
{
gerenciaArma = GetComponent<GerenciaArma>();
ZoomCameraIn = transform.Find(Tags.LOOK_ROOT).transform.Find(Tags.ZOOM_CAMERA).GetComponent<Animator>();
mira = GameObject.FindWithTag(Tags.MIRA);
Maincamera = Camera.main;
}
// Update is called once per frame
void Update()
{
Atira();
ZoomInAndOut();
}
void Atira()
{
if (Input.GetMouseButtonDown(0))
{
if(gerenciaArma.SelecionaArma().tipoBala == WeaponBulletType.BULLET)
{
gerenciaArma.SelecionaArma().AnimacaoTiro();
DisparaBala();
}
}
}
void ZoomInAndOut()
{
if (gerenciaArma.SelecionaArma().mira_tipo == TipoMira.AIM)
{
if (Input.GetMouseButtonDown(1))
{
ZoomCameraIn.Play(Animacoes.ZOOM_IN_ANIM);
// gerenciaArma.SelecionaArma().Aim(true);
mira.SetActive(false);
print("VaiZoom");
}
if (Input.GetMouseButtonUp(1))//
{
ZoomCameraIn.Play(Animacoes.ZOOM_OUT_ANIM);
//gerenciaArma.SelecionaArma().Aim(false);
mira.SetActive(true);
}
}
}
void DisparaBala()
{
RaycastHit hit;
if(Physics.Raycast(Maincamera.transform.position, Maincamera.transform.forward, out hit))
{
if (hit.transform.tag == Tags.ENEMY_TAG)
{
hit.transform.GetComponent<ScriptVida>().DanoAplicado(damage);
}
}
}
}
And this one is attached to the enemies:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class ScriptVida : MonoBehaviour
{
private IndioAnimações indio_Anim;
private NavMeshAgent navAgent;
private IndioController indio_Controller;
public float vida = 100f;
public bool is_Player, is_Cannibal, is_Tiger;
private bool morto;
// Start is called before the first frame update
void Awake()
{
if (is_Tiger || is_Cannibal)
{
indio_Anim = GetComponent<IndioAnimações>();
indio_Controller = GetComponent<IndioController>();
navAgent = GetComponent<NavMeshAgent>();
}
if (is_Player)
{
}
}
public void DanoAplicado(float damage)
{
if (morto)
return;
vida -= damage;
if (is_Player)
{
}
if (is_Tiger || is_Cannibal)
{
if (indio_Controller.EnemyState == EnemyState.PATROL)
{
indio_Controller.chase_Distance = 50f;
}
}
if (vida <= 0)
{
JogadorMorre();
morto = true;
print(vida);
}
}
void JogadorMorre()
{
if (is_Cannibal)//
{
GetComponent<Animator>().enabled = false;
GetComponent<BoxCollider>().isTrigger = false;
GetComponent<Rigidbody>().AddTorque(-transform.forward * 50f);
indio_Controller.enabled = false;
navAgent.enabled = false;
indio_Anim.enabled = false;
}
if (is_Tiger)
{
GetComponent<Animator>().enabled = false;
GetComponent<BoxCollider>().isTrigger = false;
GetComponent<Rigidbody>().AddTorque(-transform.forward * 50f);
indio_Controller.enabled = false;
navAgent.enabled = false;
indio_Anim.enabled = false;
}
if (is_Player)
{
GameObject[] enemies = GameObject.FindGameObjectsWithTag(Tags.ENEMY_TAG);
for (int i = 0; i < enemies.Length; i++)
{
enemies[i].GetComponent<IndioController>().enabled = false;
}
GetComponent<Movimentação>().enabled = false;
GetComponent<DisparaArma>().enabled = false;
GetComponent<GerenciaArma>().SelecionaArma().gameObject.SetActive(false);
}
if (tag == Tags.PLAYER_TAG)
{
Invoke("RestartGame", 3f);
}
else
{
Invoke("TurnOffGameObject", 3f);
}
}
void RestartGame()
{
UnityEngine.SceneManagement.SceneManager.LoadScene("Gameplay");
}
void TurnOffGameObject()
{
gameObject.SetActive(false);
}
}
I think the problem is related to the box collider.
How could I solve this guys?
I am new to C# and Unity and I have read this entire forum and I am still stuck. This is the error I am getting:
NullReferenceException: Object reference not set to an instance of an object
ClickToMove.Update () (at Assets/Scripts/ClickToMove.cs:27)
This is what I have...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class ClickToMove : MonoBehaviour {
[Header("Stats")]
public float attackDistance;
public float attackRate;
private float nextAttack;
private NavMeshAgent navMeshAgent;
private Animator anim;
private Transform targetedEnemy;
private bool enemyClicked;
private bool walking;
void Awake ()
{
anim = GetComponent<Animator>();
navMeshAgent = GetComponent<NavMeshAgent>();
}
// Update is called once per frame
void Update ()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Input.GetButtonDown("Fire2"))
{
if (Physics.Raycast(ray, out hit, 1000))
{
if (hit.collider.tag == "Enemy")
{
targetedEnemy = hit.transform;
enemyClicked = true;
//print("Enemy Hit");
}
else
{
walking = true;
enemyClicked = false;
navMeshAgent.isStopped = false;
navMeshAgent.destination = hit.point;
}
}
}
if (enemyClicked)
{
MoveAndAttack();
}
if (navMeshAgent.remainingDistance <= navMeshAgent.stoppingDistance)
{
walking = false;
}
else
{
walking = true;
}
//anim.SetBool("isWalking", walking);
}
void MoveAndAttack()
{
if(targetedEnemy == null)
{
return;
}
navMeshAgent.destination = targetedEnemy.position;
if(navMeshAgent.remainingDistance > attackDistance)
{
navMeshAgent.isStopped = false;
walking = true;
}
else
{
transform.LookAt(targetedEnemy);
Vector3 dirToAttack = targetedEnemy.transform.position - transform.position;
if(Time.time > nextAttack)
{
nextAttack = Time.time + attackRate;
}
navMeshAgent.isStopped = true;
walking = false;
}
}
}
Line 27 starts with "Ray ray = Camera.main.ScreenPointToRay..."
You need to have a camera in your scene with the MainCamera tag in order to call Camera.main.ScreenPointToRay(). Without this, Camera.main does not exist, resulting in a null reference exception.