Unity Missile Script - randomly a missile spirals out of control - c#

I have a homing missile script that seems to work 99% of the time, but every so often one of the missiles will start spiralling out of control and not towards the player. I can't see any reason for it, I can't see a reason for the behaviour in the code and I'm after a pair of fresh eye's to take a look and see if I'm missing something obvious. The script below is attached to each missile.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class missileControl : MonoBehaviour
{
public Transform missileTarget;
public GameObject indicator;
private int scorePerHit = 1;
private int scorePerDestroy = 50;
private int hits = 1;
[Header("Enemy Culling Variables")]
[HideInInspector]
public float distanceToCull = 4f;
[HideInInspector]
private Transform spaceShip;
public Rigidbody missileRigidbody;
[Header("Missile Control Variables")]
public float turn = 0.9f;
private float initialTurn = 0.9f;
public float missileVelocity = 95f;
private float initialMissileVelocity = 95f;
private Vector3 resetMissileVelocity = new Vector3(0f,0f,0f);
private Transform myTransform;
private float wiggleMultiplyer = 40f;
[Header("Firing Audio")]
public float minPitch = 0.9f;
public float maxPitch = 1f;
public AudioClip indicatorClip;
public TrailRenderer trailRenderer;
private bool indicatorOff = true;
private float currentDistance = 100f;
public float indicatorDist = 300f;
private IEnumerator delayAimTimer;
private void Start()
{
spaceShip = LevelVariables.currentLevelVariables.spaceShip.transform; // Player to test if behind
missileTarget = LevelVariables.currentLevelVariables.playerTarget.transform; // Target
missileRigidbody.velocity = resetMissileVelocity;
ResetVariables();
}
private void OnEnable()
{
ResetVariables();
}
private void OnDisable()
{
missileRigidbody.velocity = resetMissileVelocity;
}
void ResetVariables()
{
trailRenderer.enabled = false;
StartCoroutine(DelayTrails());
indicatorOff = true;
turn = Random.Range(initialTurn * 0.85f, initialTurn * 1.15f);
wiggleMultiplyer = Random.Range(0 - (wiggleMultiplyer), wiggleMultiplyer);
missileRigidbody.velocity = resetMissileVelocity;
missileVelocity = Random.Range(initialMissileVelocity * 0.85f, initialMissileVelocity * 1.15f);
missileRigidbody.velocity = transform.forward * missileVelocity;
}
IEnumerator DelayTrails()
{
yield return new WaitForSeconds(0.15f);
trailRenderer.Clear();
trailRenderer.enabled = true;
}
private void FixedUpdate()
{
if (GameStateController.gameStateController.gameState == GameStateController.GameState.PLAYERSTART)
{
if (Vector3.Angle((gameObject.transform.position - spaceShip.position), spaceShip.transform.forward) > 90)
{
if ((gameObject.transform.position - spaceShip.position).sqrMagnitude > distanceToCull * distanceToCull)
{
KillEnemy();
return;
}
}
else
{
if (indicatorOff)
{
currentDistance = Vector3.Distance(missileTarget.position, transform.position);
if (currentDistance <= indicatorDist)
{
indicator.SetActive(true);
PlayAudioSound(indicatorClip);
indicatorOff = false;
}
}
//missileRigidbody.velocity = (transform.forward * missileVelocity) + (transform.right * (Mathf.Sin(Time.time) * wiggleMultiplyer)) + (transform.up * (Mathf.Cos(Time.time) * wiggleMultiplyer));
missileRigidbody.velocity = transform.forward * missileVelocity;
var rocketTargetRotation = Quaternion.LookRotation(missileTarget.position - transform.position);
missileRigidbody.MoveRotation(Quaternion.RotateTowards(transform.rotation, rocketTargetRotation, turn));
}
}
else
{
StartCoroutine(DestroyGameObject(gameObject, 0f));
}
}
void OnCollisionEnter(Collision hit)
{
switch (hit.gameObject.tag)
{
case "environment":
KillEnemy();
break;
case "enemy":
KillEnemy();
break;
case "enemyBullet":
break;
case "player":
CameraShake.Shake(1f, 0.25f);
float deathScale = Random.Range(5f * transform.localScale.x, 10f * transform.localScale.x);
GameObject fx = ObjectPooler.currentPool.enemyHits.Spawn();
if (fx == null) return;
fx.transform.position = transform.position;
fx.transform.rotation = Quaternion.identity;
fx.transform.parent = hit.transform;
fx.transform.localScale = new Vector3(deathScale, deathScale, deathScale);
fx.SetActive(true);
KillEnemy();
break;
case "playerBullet":
ProcessHit();
if (hits < 1)
{
LevelVariables.currentLevelVariables.scoreBoard.ScoreHit(scorePerDestroy);
KillEnemy();
}
break;
}
}
private void ProcessHit()
{
LevelVariables.currentLevelVariables.scoreBoard.ScoreHit(scorePerHit);
hits = hits - 1;
}
private void KillEnemy()
{
GameObject fx = ObjectPooler.currentPool.enemyDeath.Spawn();
if (fx == null) return;
fx.transform.position = transform.position;
fx.transform.rotation = Quaternion.identity;
fx.transform.parent = LevelVariables.currentLevelVariables.spawnParent;
float deathScale = 1f;
deathScale = Random.Range(1f * transform.localScale.x, 4f * transform.localScale.x);
fx.transform.localScale = new Vector3(deathScale, deathScale, deathScale);
fx.SetActive(true);
StartCoroutine(DestroyGameObject(gameObject, 0f));
}
public void PlayAudioSound(AudioClip clip)
{
LevelVariables.currentLevelVariables.computerAudioSource.volume = 1f;
LevelVariables.currentLevelVariables.computerAudioSource.PlayOneShot(clip);
}
IEnumerator DestroyGameObject(GameObject turnOffObject, float waitTime)
{
yield return new WaitForSeconds(waitTime);
trailRenderer.Clear();
trailRenderer.enabled = false;
turnOffObject.Recycle();
}
}
The section below is the code for creating the missile and is part of the enemy weapon firing script.
GameObject missileObj = ObjectPooler.currentPool.destroyerMissileAmmo.Spawn();
if (missileObj == null) yield break;
CreateMuzzleFlash(muzzleLocation);
//LevelVariables.currentLevelVariables.globalMissileAmount = LevelVariables.currentLevelVariables.globalMissileAmount + 1;
missileObj.transform.localScale = new Vector3(2f, 2f, 2f);
missileObj.transform.position = muzzleLocation.transform.position;
missileObj.transform.rotation = muzzleLocation.transform.rotation;
//missileObj.transform.LookAt(m_target.transform);
missileObj.SetActive(true);
I don't see any problems with this code that would cause a missile not to head towards the player, does anyone have any idea's

Related

DistanceJoint2D grappling hook affects gravity of player in Unity2D

So I am trying to create a game where a player can swing with a rope/grappling hook, similar to a game like Teeworlds. The grappling hook feels great when I am hooked onto things and I am using my movement keys, the problem comes when I let go of my left or right movement keys the character slowly floats down. Feels like the gravity gets put to like 0.00001 on the character until i let go of the grappling hook button.
Will post a gif of how it looks and the code I am using for the grappling hook.
Thanks,
The Pepsidi.
Game Play of Issue
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class GrappleSystem : MonoBehaviour
{
public GameObject grappleAnchor;
public DistanceJoint2D grappleJoint;
public Transform crosshair;
public PlayerMovement playerMovement;
private bool grappleAttached;
private Vector2 playerPosition;
private Rigidbody2D grappleAnchorRb;
private SpriteRenderer grappleAnchorSprite;
public LineRenderer grappleRenderer;
public LayerMask grappleLayerMask;
private float grappleMaxCastDistance = 20f;
private List<Vector2> grapplePositions = new List<Vector2>();
private bool distanceSet;
void Awake()
{
grappleJoint.enabled = false;
playerPosition = transform.position;
grappleAnchorRb = grappleAnchor.GetComponent<Rigidbody2D>();
grappleAnchorSprite = grappleAnchor.GetComponent<SpriteRenderer>();
}
void Update()
{
var worldMousePosition = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0f));
var facingDirection = worldMousePosition - transform.position;
var aimAngle = Mathf.Atan2(facingDirection.y, facingDirection.x);
if (aimAngle < 0f)
{
aimAngle = Mathf.PI * 2 + aimAngle;
}
var aimDirection = Quaternion.Euler(0, 0, aimAngle * Mathf.Rad2Deg) * Vector2.right;
playerPosition = transform.position;
if (!grappleAttached)
{
SetCrosshairPosition(aimAngle);
}
HandleInput(aimDirection);
UpdateGrapplePositions();
}
private void SetCrosshairPosition(float aimAngle)
{
var x = transform.position.x + 5f * Mathf.Cos(aimAngle);
var y = transform.position.y + 5f * Mathf.Sin(aimAngle);
var crossHairPosition = new Vector3(x, y, 0);
crosshair.transform.position = crossHairPosition;
}
private void HandleInput(Vector2 aimDirection)
{
if (Input.GetMouseButtonDown(1))
{
if (grappleAttached) return;
grappleRenderer.enabled = true;
var hit = Physics2D.Raycast(playerPosition, aimDirection, grappleMaxCastDistance, grappleLayerMask);
if (hit.collider != null)
{
grappleAttached = true;
if (!grapplePositions.Contains(hit.point))
{
transform.GetComponent<Rigidbody2D>().AddForce(new Vector2(0f, 5f), ForceMode2D.Force);
grapplePositions.Add(hit.point);
grappleJoint.distance = Vector2.Distance(playerPosition, hit.point);
grappleJoint.enabled = true;
grappleAnchorSprite.enabled = true;
}
}
else
{
grappleRenderer.enabled = false;
grappleAttached = false;
grappleJoint.enabled = false;
}
}
if (Input.GetMouseButtonUp(1))
{
ResetGrapple();
}
}
private void ResetGrapple()
{
grappleJoint.enabled = false;
grappleAttached = false;
//playerMovement.isSwinging = false;
grappleRenderer.positionCount = 2;
grappleRenderer.SetPosition(0, transform.position);
grappleRenderer.SetPosition(1, transform.position);
grapplePositions.Clear();
grappleAnchorSprite.enabled = false;
}
private void UpdateGrapplePositions()
{
if (!grappleAttached)
{
return;
}
grappleRenderer.positionCount = grapplePositions.Count + 1;
for (var i = grappleRenderer.positionCount - 1; i >= 0; i--)
{
if (i != grappleRenderer.positionCount - 1)
{
grappleRenderer.SetPosition(i, grapplePositions[i]);
if (i == grapplePositions.Count - 1 || grapplePositions.Count == 1)
{
var grapplePosition = grapplePositions[grapplePositions.Count - 1];
if (grapplePositions.Count == 1)
{
grappleAnchorRb.transform.position = grapplePosition;
if (!distanceSet)
{
grappleJoint.distance = Vector2.Distance(transform.position, grapplePosition);
distanceSet = true;
}
}
else
{
grappleAnchorRb.transform.position = grapplePosition;
if (!distanceSet)
{
grappleJoint.distance = Vector2.Distance(transform.position, grapplePosition);
distanceSet = true;
}
}
}
else if (i - 1 == grapplePositions.IndexOf(grapplePositions.Last()))
{
var grapplePosition = grapplePositions.Last();
grappleAnchorRb.transform.position = grapplePosition;
if (!distanceSet)
{
grappleJoint.distance = Vector2.Distance(transform.position, grapplePosition);
distanceSet = true;
}
}
}
else
{
grappleRenderer.SetPosition(i, transform.position);
}
}
}
}

Why when pressing the b key the transform is moving backward but not in the same duration when moving forward?

For example the duration is set to 10 seconds. When the flag bool go is true the transform will move in 10 seconds to the target(destinationTransform). but when I press the b key in the middle while the transform is moving forward the transform start moving backward to the original position but not in 10 seconds but faster.
Is that because the distance is not the same as when it's moving forward ?
I'm trying to do that when i press the b key in the middle the transform will move backward but in the duration time no matter the distance. maybe i messed the lerp code in the backward state ?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Cinemachine;
public class MoveToTarget : MonoBehaviour
{
public enum TransitionState
{
None,
MovingTowards,
MovingBackward,
Transferring
}
public Transform destinationTransform;
public bool isChild = false;
public AnimationCurve curve = AnimationCurve.EaseInOut(0.0f, 0.0f, 1.0f, 1.0f);
public float duration = 10.0f;
public bool go = false;
private float t;
private Transform originTransform;
private float timer;
private TransitionState state = TransitionState.MovingTowards;
private Vector3 originPosition;
private SphereCollider col;
private bool enableCollider = true;
private bool updateOriginPosition = true;
void Start()
{
t = 0.0f;
curve.postWrapMode = WrapMode.Once;
originPosition = transform.position;
col = GetComponent<SphereCollider>();
}
void Update()
{
if(Input.GetKeyDown(KeyCode.B))
{
t = 0.0f;
state = TransitionState.MovingBackward;
}
if (go)
{
if (updateOriginPosition == true)
{
originPosition = transform.position;
updateOriginPosition = false;
}
if (col != null && enableCollider)
{
//col.enabled = false;
//transform.GetComponent<Rigidbody>().isKinematic = true;
Destroy(col);
Destroy(transform.GetComponent<Rigidbody>());
//transform.GetComponent<InteractableItem>().enabledInteraction = false;
enableCollider = false;
}
switch (state)
{
case TransitionState.MovingTowards:
var v = destinationTransform.position - transform.position;
if (v.magnitude < 0.001f)
{
state = TransitionState.Transferring;
originTransform = destinationTransform;
timer = 0;
return;
}
t += Time.deltaTime;
float s = t / duration;
transform.position = Vector3.Lerp(originPosition,
destinationTransform.position, curve.Evaluate(s));
break;
case TransitionState.MovingBackward:
t += Time.deltaTime;
float s1 = t / duration;
transform.position = Vector3.Lerp(transform.position,
transform.parent.position,
curve.Evaluate(s1));
break;
case TransitionState.Transferring:
timer += Time.deltaTime;
this.transform.position = Vector3.Lerp(originTransform.position, destinationTransform.position, timer);
if (timer >= 1.0f)
{
this.transform.parent = destinationTransform;
transform.localPosition = new Vector3(0, 0, 0);
isChild = true;
go = false;
state = TransitionState.None;
this.enabled = false;
return;
}
break;
default:
this.enabled = false;
return;
}
}
}
}
The solution is first to update the originPosition in the Update when pressing the B key :
if(Input.GetKeyDown(KeyCode.B))
{
t = 0.0f;
originPosition = transform.position;
state = TransitionState.MovingBackward;
}
Then in the MovingBackward state to set the originPosition instead the transform.position.
case TransitionState.MovingBackward:
t += Time.deltaTime;
float s1 = t / duration;
transform.position = Vector3.Lerp(originPosition,
transform.parent.position,
curve.Evaluate(s1));
break;
The complete code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Cinemachine;
public class MoveToTarget : MonoBehaviour
{
public enum TransitionState
{
None,
MovingTowards,
MovingBackward,
Transferring
}
public Transform destinationTransform;
public bool isChild = false;
public AnimationCurve curve = AnimationCurve.EaseInOut(0.0f, 0.0f, 1.0f, 1.0f);
public float duration = 10.0f;
public bool go = false;
private float t;
private Transform originTransform;
private float timer;
private TransitionState state = TransitionState.MovingTowards;
private Vector3 originPosition;
private SphereCollider col;
private bool enableCollider = true;
private bool updateOriginPosition = true;
void Start()
{
t = 0.0f;
curve.postWrapMode = WrapMode.Once;
originPosition = transform.position;
col = GetComponent<SphereCollider>();
}
void Update()
{
if(Input.GetKeyDown(KeyCode.B))
{
t = 0.0f;
originPosition = transform.position;
state = TransitionState.MovingBackward;
}
if (go)
{
if (updateOriginPosition == true)
{
originPosition = transform.position;
updateOriginPosition = false;
}
if (col != null && enableCollider)
{
Destroy(col);
Destroy(transform.GetComponent<Rigidbody>());
enableCollider = false;
}
switch (state)
{
case TransitionState.MovingTowards:
var v = destinationTransform.position - transform.position;
if (v.magnitude < 0.001f)
{
state = TransitionState.Transferring;
originTransform = destinationTransform;
timer = 0;
return;
}
t += Time.deltaTime;
float s = t / duration;
transform.position = Vector3.Lerp(originPosition,
destinationTransform.position, curve.Evaluate(s));
break;
case TransitionState.MovingBackward:
t += Time.deltaTime;
float s1 = t / duration;
transform.position = Vector3.Lerp(originPosition,
transform.parent.position,
curve.Evaluate(s1));
break;
case TransitionState.Transferring:
timer += Time.deltaTime;
this.transform.position = Vector3.Lerp(originTransform.position, destinationTransform.position, timer);
if (timer >= 1.0f)
{
this.transform.parent = destinationTransform;
transform.localPosition = new Vector3(0, 0, 0);
isChild = true;
go = false;
state = TransitionState.None;
this.enabled = false;
return;
}
break;
default:
this.enabled = false;
return;
}
}
}
}

Coding smoother Shooting Recoil

So, I started following a tutorial and then added some other things that I needed and everything works fine, even the recoil, but the problem is that it is really choppy, it moves once a frame and it isn't smooth at all (which is what I want) I don't know a lot about programming so I hope you can help me :)
My code:
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Audio;
public class GunController : MonoBehaviour
{
[Header("Gun Setting")]
public float fireRate = 0.1f;
public int clipSize = 30;
public int reservedAmmoCapacity = 270;
//Variables that change throughout the code
bool canShoot;
int _currentAmmoInClip;
int _ammoInReserve;
//Muzzle Flash
public ParticleSystem muzzleFlash;
//Aiming
public Vector3 normalLocalPosition;
public Vector3 aimingLocalPosition;
public float aimSmoothing = 10;
[Header("Mouse Settings")]
public float mouseSensitivity = 1;
Vector2 _currentRotation;
public float weaponSwayAmount = 10;
//Weapon Recoil
public bool randomizeRecoil;
public Vector2 randomRecoilConstraints;
//You only need to assign if randomize recoil is off
public Vector2[] recoilPattern;
//Audio
AudioSource shootingSound;
//Reloading
public float reloadTime = 1.5f;
private void Start()
{
_currentAmmoInClip = clipSize;
_ammoInReserve = reservedAmmoCapacity;
canShoot = true;
shootingSound = GetComponent<AudioSource>();
}
private void Update()
{
DetermineAim();
DetermineRotation();
if (Input.GetMouseButton(0) && canShoot && _currentAmmoInClip > 0)
{
shootingSound.Play();
StartCoroutine(FinishShooting());
muzzleFlash.Play();
canShoot = false;
_currentAmmoInClip--;
StartCoroutine(ShootGun());
}
else if (Input.GetKeyDown(KeyCode.R) && _currentAmmoInClip < clipSize && _ammoInReserve > 0)
{
StartCoroutine(Reload());
}
}
void DetermineRotation()
{
Vector2 mouseAxis = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
mouseAxis *= mouseSensitivity;
_currentRotation += mouseAxis;
_currentRotation.y = Mathf.Clamp(_currentRotation.y, -90, 90);
transform.localPosition += (Vector3)mouseAxis * weaponSwayAmount / 1000;
transform.root.localRotation = Quaternion.AngleAxis(_currentRotation.x, Vector3.up);
transform.parent.localRotation = Quaternion.AngleAxis(-_currentRotation.y, Vector3.right);
}
void DetermineAim()
{
Vector3 target = normalLocalPosition;
if (Input.GetMouseButton(1)) target = aimingLocalPosition;
Vector3 desiredPosition = Vector3.Lerp(transform.localPosition, target, Time.deltaTime * aimSmoothing);
transform.localPosition = desiredPosition;
}
void DetermineRecoil()
{
transform.localPosition -= Vector3.forward * 0.1f;
if (randomizeRecoil)
{
float xRecoil = Random.Range(-randomRecoilConstraints.x, randomRecoilConstraints.x);
float yRecoil = Random.Range(-randomRecoilConstraints.y, randomRecoilConstraints.y);
Vector2 recoil = new Vector2(xRecoil, yRecoil);
_currentRotation += recoil;
}
else
{
int currentStep = clipSize + 1 - _currentAmmoInClip;
currentStep = Mathf.Clamp(currentStep, 0, recoilPattern.Length - 1);
_currentRotation += recoilPattern[currentStep];
}
}
IEnumerator ShootGun()
{
_currentAmmoInClip -= 1;
DetermineRecoil();
RayCastEnemy();
yield return new WaitForSeconds(fireRate);
canShoot = true;
}
void RayCastEnemy()
{
RaycastHit hit;
if (Physics.Raycast(transform.parent.position, transform.parent.forward, out hit, 1 << LayerMask.NameToLayer("Enemy")))
{
try
{
Debug.Log("Hit an enemy");
Rigidbody rb = hit.transform.GetComponent<Rigidbody>();
rb.constraints = RigidbodyConstraints.None;
rb.AddForce(transform.parent.transform.forward * 50);
}
catch { }
}
}
IEnumerator FinishShooting()
{
yield return new WaitForSeconds(0.3f);
shootingSound.Stop();
}
IEnumerator Reload()
{
canShoot = false;
yield return new WaitForSeconds(reloadTime);
int amountNeeded = clipSize - _currentAmmoInClip;
if (amountNeeded > _ammoInReserve)
{
_currentAmmoInClip += _ammoInReserve;
_ammoInReserve -= amountNeeded;
canShoot = true;
}
else
{
canShoot = false;
_currentAmmoInClip = clipSize;
_ammoInReserve -= amountNeeded;
canShoot = true;
}
}
}
I don't see the function DetermineRecoil() called anywhere in the code, but maybe this solution will work:
let _currentRotation = Vector2.Lerp(_currentRotation, _currentRotation + recoilPattern[currentStep], 10*Time.deltaTime);
It will change the value of _currentRotation smoothly.

Movement Object and Comparing indetical Vector3 in ArrayList

I am writing a C# script on Unity 3D.
I'm working on pathfinding now.
The path has been found correctly in the Array List and the Object can move according to the path with a constant speed.
Then, I want to improvise, where when the path found is a straight line, the object will increase its speed. Meanwhile, when the path turns the object will reduce its speed again.
Here, I don't know how to group between straight and turning paths in an arrayList.
Thankyou for helping me :)
This is the code :
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
public abstract class Unit : MonoBehaviour
{
#region public variables
public GameObject Astar;
public bool drawGizmos = false;
protected float gravity = 9.8f;
public Transform target;
public Transform NPC;
public Vector3 lastTargetPosition;
public float movementSpeed;
public float rotationSpeed = 85;
protected float distanceToPath = 1;
public Vector2 currentPosition = new Vector2(0, 0);
protected int spacesMoved = 0;
// Default action times to 5 second interval
protected float period = 1f;
protected float nextActionTime = 1f;
protected bool isSafeToUpdatePath = false;
protected int pathFoundCount = 0;
protected bool isMoving = false;
protected bool isTargetReached = false;
#endregion
#region member variables
public Vector3[] m_path;
protected int m_targetIndex;
protected CharacterController m_characterController;
private Node lastNodePosition;
private List<Node> lastPositionNeighbors;
private Vector3 m_lastKnownPosition;
private Quaternion m_lookAtRotation;
private GridSystem m_grid;
private Coroutine lastRoutine = null;
private bool preventExtraNodeUpdate = false;
public Stopwatch timer;
#endregion
public virtual void Awake()
{
timer = new Stopwatch();
if (Astar != null)
m_grid = Astar.GetComponent<GridSystem>();
}
public virtual void Start()
{
m_characterController = GetComponent<CharacterController>();
timer.Reset();
timer.Start();
PathRequestManager.RequestPath(transform.position, target.position, OnPathFound);
lastTargetPosition = target.position;
UnityEngine.Debug.Log("NPC Position : " + transform.position);
UnityEngine.Debug.Log("Target Position : " + target.position);
}
public virtual void Update()
{
if (Time.time > nextActionTime) //update path setiap 1f
{
nextActionTime += period;
isSafeToUpdatePath = true;
}
else
{
isSafeToUpdatePath = false;
}
//If we don't check !isMoving the AI may get stuck waiting to update the grid for nextActionTime.
if (target.position != lastTargetPosition)
{
isMoving = true;
UpdateNodePosition();
UpdatePath();
UpdateRotation();
}
lastTargetPosition = target.position;
}
public void UpdatePath()
{
lastNodePosition.walkable = Walkable.Passable;
PathRequestManager.RequestPath(transform.position, target.position, OnPathFound);
}
public virtual void OnPathFound(Vector3[] newPath, bool pathSuccessful)
{
if (pathSuccessful)
{
pathFoundCount++;
m_path = newPath;
m_targetIndex = 0;
// Stop coroutine if it is already running.
if (lastRoutine != null)
StopCoroutine(lastRoutine);
lastRoutine = StartCoroutine(FollowPath());
}
}
public float time;
public virtual IEnumerator FollowPath()
{
Vector3 currentPath = m_path[0];
while (true)
{
if (Vector3.Distance(transform.position, currentPath) < distanceToPath)
{
m_targetIndex++;
// If we are done with path.
if (m_targetIndex >= m_path.Length)
{
timer.Stop();
UnityEngine.Debug.Log("Time Move : " + timer.ElapsedMilliseconds);
isMoving = false;
yield break;
}
currentPath = m_path[m_targetIndex];
}
float Distance = Vector3.Distance(NPC.transform.position, target.transform.position);
UnityEngine.Debug.Log("Distance : " + Distance);
// Occurs each frame
//move follow path
UpdatePosition(currentPath);
yield return null;
}
}
public virtual void UpdatePosition(Vector3 destination)
{
Node node = m_grid.NodeFromWorldPoint(transform.position);
Vector3 direction = destination - transform.position;
movementSpeed = 1;
transform.Translate(direction.normalized * movementSpeed * Time.deltaTime, Space.World);
UnityEngine.Debug.Log("Speed NPC : " + movementSpeed);
}
public virtual void UpdateRotation()
{
m_lastKnownPosition = target.transform.position;
m_lookAtRotation = Quaternion.LookRotation(m_lastKnownPosition - transform.position);
if (transform.rotation != m_lookAtRotation)
transform.rotation = Quaternion.RotateTowards(transform.rotation, m_lookAtRotation, rotationSpeed * Time.deltaTime);
}
public void UpdateNodePosition()
{
Node node = m_grid.NodeFromWorldPoint(transform.position);
if (isMoving == false)
{
lastPositionNeighbors = m_grid.GetNeighbours(node);
foreach (Node n in lastPositionNeighbors)
{
if (n.walkable != Walkable.Impassable)
n.walkable = Walkable.Blocked;
}
node.walkable = Walkable.Blocked;
lastNodePosition = node;
currentPosition = new Vector2(node.gridX, node.gridY);
return;
}
if (lastNodePosition != null && isMoving)
{
preventExtraNodeUpdate = false;
lastPositionNeighbors = m_grid.GetNeighbours(node);
lastNodePosition.walkable = Walkable.Passable;
if (lastPositionNeighbors != null)
foreach (Node n in lastPositionNeighbors)
{
if (n.walkable != Walkable.Impassable)
n.walkable = Walkable.Passable;
}
if (!node.Equals(lastNodePosition))
spacesMoved++;
}
else
{
node.walkable = Walkable.Blocked;
lastNodePosition = node;
currentPosition = new Vector2(node.gridX, node.gridY);
}
}
public void OnDrawGizmos()
{
if (!drawGizmos)
return;
if (m_path != null)
{
for (int i = m_targetIndex; i < m_path.Length; i++)
{
Gizmos.color = Color.black;
Gizmos.DrawCube(m_path[i], Vector3.one);
}
}
}
}
This screenshot after running
Okay. It looks to me like all that you have to do in order to determine if you are on a curved path is to check if the next step you are going to take is directly in front of the player. You can do this in your UpdatePosition function. Just check if the direction you are about to move in has the same x or z position. Assuming that y is up and all points on your grid have the same y position. In the case that you are moving horizontally, x will stay the same, and in the case that you are moving vertically, z will stay the same. Or vice versa.
public virtual void UpdatePosition(Vector3 destination)
{
Node node = m_grid.NodeFromWorldPoint(transform.position);
Vector3 direction = destination - transform.position;
if(destination.x == transform.position.x || destination.z == transform.position.z)
{
//Direction is staying the same
movementSpeed = 1f;
}else{
movementSpeed = 0.5f;
}
transform.Translate(direction.normalized * movementSpeed * Time.deltaTime, Space.World);
UnityEngine.Debug.Log("Speed NPC : " + movementSpeed);
}
You should be able to customize the movement speed however you want from there. IF you're having issues still after this, try printing out the (x,y,z) components of the destination and the transform and see where they are similar when the path is straight and what changes when the path is curved. The code above assumes the y never changes.

Automatic grid movement

I would like to know how can I modify my code for my enemy to be able to move automatically in my grid ?
This is my code below :
[using System.Collections;
using UnityEngine;
class Enemy : MonoBehaviour {
private float moveSpeed = 50f;
private float gridSize = 18f;
private enum Orientation {
Horizontal,
Vertical
};
private Orientation gridOrientation = Orientation.Vertical;
private bool allowDiagonals = false;
private bool correctDiagonalSpeed = true;
private Vector2 input;
private bool isMoving = false;
private Vector3 startPosition;
private Vector3 endPosition;
private float t;
private float factor;
public void Update() {
if (!isMoving) {
input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
if (!allowDiagonals) {
if (Mathf.Abs(input.x) > Mathf.Abs(input.y)) {
input.y = 0;
} else {
input.x = 0;
}
}
if (input != Vector2.zero) {
StartCoroutine(move(transform));
}
}
}
public IEnumerator move (Transform transform)
{
isMoving = true;
startPosition = transform.position;
t = 0;
if (gridOrientation == Orientation.Horizontal) {
endPosition = new Vector3 (startPosition.x + System.Math.Sign (input.x) * gridSize,
startPosition.y, startPosition.z + System.Math.Sign (input.y) * gridSize);
} else {
endPosition = new Vector3 (startPosition.x + System.Math.Sign (input.x) * gridSize,
startPosition.y + System.Math.Sign (input.y) * gridSize, startPosition.z);
}
if (allowDiagonals && correctDiagonalSpeed && input.x != 0 && input.y != 0) {
factor = 0.7071f;
} else {
factor = 1f;
}
while (t < 1f) {
t += Time.deltaTime * (moveSpeed / gridSize) * factor;
transform.position = Vector3.Lerp (startPosition, endPosition, t);
yield return null;
}
isMoving = false;
yield return 0;
}
}
]

Categories

Resources