What i'm trying to do is once the random flag is true move the player between the waypoints randomly.
but just calling the random method is not enough.
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class Waypoints : MonoBehaviour
{
public GameObject[] waypoints;
public Transform target;
public float moveSpeed = 10f;
public float slowDownSpeed = 3f;
public float reverseSlowDownSpeed = 3f;
public float rotationSpeed = 1f;
private int targetsIndex = 0;
private Vector3 originalPosition;
private GameObject[] players;
public Transform reverseTarget;
private int reverseTargetsIndex = 0;
private Vector3 reverseOriginalPosition;
public bool random = false;
// Use this for initialization
void Start()
{
waypoints = GameObject.FindGameObjectsWithTag("Blocks");
players = GameObject.FindGameObjectsWithTag("Player");
originalPosition = players[0].transform.localPosition;
}
// Update is called once per frame
void Update()
{
if (random == true)
{
RandomWayPointsAI();
}
else
{
WayPointsAI();
}
}
private void WayPointsAI()
{
if (targetsIndex == waypoints.Length)
targetsIndex = 0;
target = waypoints[targetsIndex].transform;
float distance = Vector3.Distance(players[0].transform.position, target.transform.position);
players[0].transform.localRotation = Quaternion.Slerp(players[0].transform.localRotation, Quaternion.LookRotation(target.position - players[0].transform.localPosition), rotationSpeed * Time.deltaTime);
//move towards the player
if (distance < 30)
{
players[0].transform.localPosition += players[0].transform.forward * slowDownSpeed * Time.deltaTime;
}
else
{
players[0].transform.localPosition += players[0].transform.forward * moveSpeed * Time.deltaTime;
}
if (distance < target.transform.localScale.magnitude)
{
targetsIndex++;
}
}
private void ReverseWayPointsAI()
{
if (reverseTargetsIndex == 0)
reverseTargetsIndex = waypoints.Length - 1;
reverseTarget = waypoints[reverseTargetsIndex].transform;
float distance = Vector3.Distance(players[1].transform.position, reverseTarget.transform.position);
players[1].transform.rotation = Quaternion.Slerp(players[1].transform.rotation, Quaternion.LookRotation(reverseTarget.position - players[1].transform.position), rotationSpeed * Time.deltaTime);
//move towards the player
if (distance < 30)
{
players[1].transform.position += players[1].transform.forward * reverseSlowDownSpeed * Time.deltaTime;
}
else
{
players[1].transform.position += players[1].transform.forward * moveSpeed * Time.deltaTime;
}
if (distance < reverseTarget.transform.localScale.magnitude)
{
reverseTargetsIndex--;
}
}
void RandomWayPointsAI()
{
if (random == true)
{
int index = UnityEngine.Random.Range(0, waypoints.Length);
target = waypoints[index].transform;
}
}
void DrawLinesInScene()
{
// draw lines between each checkpoint //
for (int i = 0; i < waypoints.Length - 1; i++)
{
Debug.DrawLine(waypoints[i].transform.position, waypoints[i + 1].transform.position, Color.blue);
}
// draw a line between the original transform start position
// and the current transform position //
Debug.DrawLine(originalPosition, players[0].transform.position, Color.red);
Debug.DrawLine(reverseOriginalPosition, players[1].transform.position, Color.red);
// draw a line between current transform position and the next waypoint target
// each time reached a waypoint.
if (target != null)
Debug.DrawLine(target.transform.position, players[0].transform.position, Color.green);
if (reverseTarget != null)
Debug.DrawLine(reverseTarget.transform.position, players[1].transform.position, Color.green);
}
void AddColliderToWaypoints()
{
foreach (GameObject go in waypoints)
{
SphereCollider sc = go.AddComponent<SphereCollider>() as SphereCollider;
sc.isTrigger = true;
}
}
}
Inside the Update i'm checking if random is true then calling the RandomWayPointsAI(); but it's not moving the player it's just keep picking up each frame a new random waypoint but that's it.
void Update()
{
if (random == true)
{
RandomWayPointsAI();
}
else
{
WayPointsAI();
}
}
Here is your answer. First you are not writing the movement code in the random function and you are expecting it to move.
bool getNextRandom = true;
void RandomWayPointsAI()
{
if (random == true && getNextRandom)
{
int index = UnityEngine.Random.Range(0, waypoints.Length);
target = waypoints[index].transform;
getNextRandom = false;
}
float distance = Vector3.Distance(players[0].transform.position, target.transform.position);
players[0].transform.localRotation = Quaternion.Slerp(players[0].transform.localRotation, Quaternion.LookRotation(target.position - players[0].transform.localPosition), rotationSpeed * Time.deltaTime);
//move towards the player
if (distance < 30)
{
players[0].transform.localPosition += players[0].transform.forward * slowDownSpeed * Time.deltaTime;
}
else
{
players[0].transform.localPosition += players[0].transform.forward * moveSpeed * Time.deltaTime;
}
if (distance < target.transform.localScale.magnitude)
{
getNextRandom = true;
}
}
Further you can imporve the solution by moving the movement code to another function which will give you better control
public GameObject[] waypoints;
public Transform target;
public float moveSpeed = 10f;
public float slowDownSpeed = 3f;
public float reverseSlowDownSpeed = 3f;
public float rotationSpeed = 1f;
private int targetsIndex = 0;
private Vector3 originalPosition;
private GameObject[] players;
public Transform reverseTarget;
private int reverseTargetsIndex = 0;
private Vector3 reverseOriginalPosition;
public bool random = false;
public bool getNextRandom = true;
// Use this for initialization
void Start()
{
waypoints = GameObject.FindGameObjectsWithTag("Blocks");
players = GameObject.FindGameObjectsWithTag("Player");
originalPosition = players[0].transform.localPosition;
}
// Update is called once per frame
void Update()
{
if (random == true)
{
RandomWayPointsAI();
}
else
{
WayPointsAI();
}
}
private void WayPointsAI()
{
if (targetsIndex == waypoints.Length)
targetsIndex = 0;
target = waypoints[targetsIndex].transform;
if (MovePlayer())
targetsIndex++;
}
private void ReverseWayPointsAI()
{
if (reverseTargetsIndex == 0)
reverseTargetsIndex = waypoints.Length - 1;
reverseTarget = waypoints[reverseTargetsIndex].transform;
if (MovePlayer())
reverseTargetsIndex--;
}
void RandomWayPointsAI()
{
if (random == true && getNextRandom)
{
int index = UnityEngine.Random.Range(0, waypoints.Length);
target = waypoints[index].transform;
getNextRandom = false;
}
getNextRandom = MovePlayer();
}
bool MovePlayer()
{
float distance = Vector3.Distance(players[0].transform.position, target.transform.position);
players[0].transform.localRotation = Quaternion.Slerp(players[0].transform.localRotation, Quaternion.LookRotation(target.position - players[0].transform.localPosition), rotationSpeed * Time.deltaTime);
//move towards the player
if (distance < 30)
{
players[0].transform.localPosition += players[0].transform.forward * slowDownSpeed * Time.deltaTime;
}
else
{
players[0].transform.localPosition += players[0].transform.forward * moveSpeed * Time.deltaTime;
}
if (distance < target.transform.localScale.magnitude)
return true;
else
return false;
}
void DrawLinesInScene()
{
// draw lines between each checkpoint //
for (int i = 0; i < waypoints.Length - 1; i++)
{
Debug.DrawLine(waypoints[i].transform.position, waypoints[i + 1].transform.position, Color.blue);
}
// draw a line between the original transform start position
// and the current transform position //
Debug.DrawLine(originalPosition, players[0].transform.position, Color.red);
Debug.DrawLine(reverseOriginalPosition, players[1].transform.position, Color.red);
// draw a line between current transform position and the next waypoint target
// each time reached a waypoint.
if (target != null)
Debug.DrawLine(target.transform.position, players[0].transform.position, Color.green);
if (reverseTarget != null)
Debug.DrawLine(reverseTarget.transform.position, players[1].transform.position, Color.green);
}
void AddColliderToWaypoints()
{
foreach (GameObject go in waypoints)
{
SphereCollider sc = go.AddComponent<SphereCollider>() as SphereCollider;
sc.isTrigger = true;
}
}
If you look at your RandomWayPointsAI() function, it only defines the index and the target but don't have any code below it to move the player.
private void WayPointsAI()
{
if (targetsIndex == waypoints.Length)
targetsIndex = 0;
target = waypoints[targetsIndex].transform;
float distance = Vector3.Distance(players[0].transform.position, target.transform.position);
players[0].transform.localRotation = Quaternion.Slerp(players[0].transform.localRotation, Quaternion.LookRotation(target.position - players[0].transform.localPosition), rotationSpeed * Time.deltaTime);
void RandomWayPointsAI()
{
//No need to check if random is true anymore, you already checked when you run this function
int index = UnityEngine.Random.Range(0, waypoints.Length);
target = waypoints[index].transform;
//float distance = Vector3.Distance(players[0].transform.position, target.transform.position);
//players[0].transform.localRotation = Quaternion.Slerp(players[0].transform.localRotation, Quaternion.LookRotation(target.position - players[0].transform.localPosition), rotationSpeed * Time.deltaTime);**
}
Related
I wanted to add Guns with recoil to my 3d fps game. It worked but for some reason all the time when i look completely downwards i walk backwards or frontwards. This only happens when the gun is active.
The Gun Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GunScript : MonoBehaviour
{
[SerializeField] float Recoil = 500f;
[SerializeField] float TimeTillNextShoot;
[SerializeField] float Range = 100f;
[SerializeField] Transform GunTipposition;
[SerializeField] float recoilRadius = 100f;
public Camera PlayerCamera;
public Rigidbody rbPlayer;
private void Update()
{
Shoot();
}
public void Shoot()
{
if (Input.GetButtonDown("Fire1"))
{
RaycastHit hit;
if(Physics.Raycast(PlayerCamera.transform.position, PlayerCamera.transform.forward, out hit, Range))
{
Debug.Log(hit.transform.name);
Enemy Enemytarget = hit.transform.GetComponent<Enemy>();
if(Enemytarget != null)
{
Enemytarget.TakeDamage(true);
}
}
if (gameObject.CompareTag("ShotGun"))
{
Transform RecoilPosition = GunTipposition.transform;
rbPlayer.AddExplosionForce(Recoil, RecoilPosition.position, recoilRadius);
}
}
}
}
The player Movement:
// Some stupid rigidbody based movement by Dani
using System;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[Header("Assignables")]
[Tooltip("this is a reference to the MainCamera object, not the parent of it.")]
public Transform playerCam;
[Tooltip("reference to orientation object, needed for moving forward and not up or something.")]
public Transform orientation;
[Tooltip("LayerMask for ground layer, important because otherwise the collision detection wont know what ground is")]
public LayerMask whatIsGround;
private Rigidbody rb;
[Header("Rotation and look")]
private float xRotation;
[Tooltip("mouse/look sensitivity")]
public float sensitivity = 50f;
private float sensMultiplier = 1.5f;
[Header("Movement")]
[Tooltip("additive force amount. every physics update that forward is pressed, this force (multiplied by 1/tickrate) will be added to the player.")]
public float moveSpeed = 4500;
[Tooltip("maximum local velocity before input is cancelled")]
public float maxSpeed = 20;
[Tooltip("normal countermovement when not crouching.")]
public float counterMovement = 0.175f;
private float threshold = 0.01f;
[Tooltip("the maximum angle the ground can have relative to the players up direction.")]
public float maxSlopeAngle = 35f;
private Vector3 crouchScale = new Vector3(1, 0.5f, 1);
private Vector3 playerScale;
[Tooltip("forward force for when a crouch is started.")]
public float slideForce = 400;
[Tooltip("countermovement when sliding. this doesnt work the same way as normal countermovement.")]
public float slideCounterMovement = 0.2f;
private bool readyToJump = true;
private float jumpCooldown = 0.25f;
[Tooltip("this determines the jump force but is also applied when jumping off of walls, if you decrease it, you may end up being able to walljump and then get back onto the wall leading to infinite height.")]
public float jumpForce = 550f;
float x, y;
bool jumping;
private Vector3 normalVector = Vector3.up;
[Header("Wallrunning")]
private float actualWallRotation;
private float wallRotationVel;
private Vector3 wallNormalVector;
[Tooltip("when wallrunning, an upwards force is constantly applied to negate gravity by about half (at default), increasing this value will lead to more upwards force and decreasing will lead to less upwards force.")]
public float wallRunGravity = 1;
[Tooltip("when a wallrun is started, an upwards force is applied, this describes that force.")]
public float initialForce = 20f;
[Tooltip("float to choose how much force is applied outwards when ending a wallrun. this should always be greater than Jump Force")]
public float escapeForce = 600f;
private float wallRunRotation;
[Tooltip("how much you want to rotate the camera sideways while wallrunning")]
public float wallRunRotateAmount = 10f;
[Tooltip("a bool to check if the player is wallrunning because thats kinda necessary.")]
public bool isWallRunning;
[Tooltip("a bool to determine whether or not to actually allow wallrunning.")]
public bool useWallrunning = true;
[Header("Collisions")]
[Tooltip("a bool to check if the player is on the ground.")]
public bool grounded;
[Tooltip("a bool to check if the player is currently crouching.")]
public bool crouching;
private bool surfing;
private bool cancellingGrounded;
private bool cancellingSurf;
private bool cancellingWall;
private bool onWall;
private bool cancelling;
public static PlayerMovement Instance { get; private set; }
void Awake()
{
Instance = this;
rb = GetComponent<Rigidbody>();
//Create a physic material with no friction to allow for wallrunning and smooth movement not being dependant
//and smooth movement not being dependant on the in-built unity physics engine, apart from collisions.
PhysicMaterial mat = new PhysicMaterial("tempMat");
mat.bounceCombine = PhysicMaterialCombine.Average;
mat.bounciness = 0;
mat.frictionCombine = PhysicMaterialCombine.Minimum;
mat.staticFriction = 0;
mat.dynamicFriction = 0;
gameObject.GetComponent<Collider>().material = mat;
}
void Start()
{
playerScale = transform.localScale;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
readyToJump = true;
wallNormalVector = Vector3.up;
}
private void FixedUpdate()
{
Movement();
}
private void Update()
{
MyInput();
Look();
}
private void LateUpdate()
{
//call the wallrunning Function
WallRunning();
WallRunRotate();
}
private void WallRunRotate()
{
FindWallRunRotation();
float num = 12f;
actualWallRotation = Mathf.SmoothDamp(actualWallRotation, wallRunRotation, ref wallRotationVel, num * Time.deltaTime);
playerCam.localRotation = Quaternion.Euler(playerCam.rotation.eulerAngles.x, playerCam.rotation.eulerAngles.y, actualWallRotation);
}
/// <summary>
/// Find user input. Should put this in its own class but im lazy
/// </summary>
private void MyInput()
{
x = Input.GetAxisRaw("Horizontal");
y = Input.GetAxisRaw("Vertical");
jumping = Input.GetButton("Jump");
crouching = Input.GetKey(KeyCode.LeftControl);
//Crouching
if (Input.GetKeyDown(KeyCode.LeftControl))
StartCrouch();
if (Input.GetKeyUp(KeyCode.LeftControl))
StopCrouch();
}
private void StartCrouch()
{
transform.localScale = crouchScale;
transform.position = new Vector3(transform.position.x, transform.position.y - 0.5f, transform.position.z);
if (rb.velocity.magnitude > 0.2f && grounded)
{
if (grounded)
{
rb.AddForce(orientation.transform.forward * slideForce);
}
}
}
private void StopCrouch()
{
transform.localScale = playerScale;
transform.position = new Vector3(transform.position.x, transform.position.y + 0.5f, transform.position.z);
}
private void Movement()
{
//Extra gravity
rb.AddForce(Vector3.down * Time.deltaTime * 10);
//Find actual velocity relative to where player is looking
Vector2 mag = FindVelRelativeToLook();
float xMag = mag.x, yMag = mag.y;
//Counteract sliding and sloppy movement
CounterMovement(x, y, mag);
//If holding jump && ready to jump, then jump
if (readyToJump && jumping) Jump();
//Set max speed
float maxSpeed = this.maxSpeed;
//If sliding down a ramp, add force down so player stays grounded and also builds speed
if (crouching && grounded && readyToJump)
{
rb.AddForce(Vector3.down * Time.deltaTime * 3000);
return;
}
//If speed is larger than maxspeed, cancel out the input so you don't go over max speed
if (x > 0 && xMag > maxSpeed) x = 0;
if (x < 0 && xMag < -maxSpeed) x = 0;
if (y > 0 && yMag > maxSpeed) y = 0;
if (y < 0 && yMag < -maxSpeed) y = 0;
//Some multipliers
float multiplier = 1f, multiplierV = 1f;
// Movement in air
if (!grounded)
{
multiplier = 0.5f;
multiplierV = 0.5f;
}
// Movement while sliding
if (grounded && crouching) multiplierV = 0f;
//Apply forces to move player
rb.AddForce(orientation.transform.forward * y * moveSpeed * Time.deltaTime * multiplier * multiplierV);
rb.AddForce(orientation.transform.right * x * moveSpeed * Time.deltaTime * multiplier);
}
private void Jump()
{
if ((grounded || isWallRunning || surfing) && readyToJump)
{
MonoBehaviour.print("jumping");
Vector3 velocity = rb.velocity;
readyToJump = false;
rb.AddForce(Vector2.up * jumpForce * 1.5f);
rb.AddForce(normalVector * jumpForce * 0.5f);
if (rb.velocity.y < 0.5f)
{
rb.velocity = new Vector3(velocity.x, 0f, velocity.z);
}
else if (rb.velocity.y > 0f)
{
rb.velocity = new Vector3(velocity.x, velocity.y / 2f, velocity.z);
}
if (isWallRunning)
{
rb.AddForce(wallNormalVector * jumpForce * 3f);
}
Invoke("ResetJump", jumpCooldown);
if (isWallRunning)
{
isWallRunning = false;
}
}
}
private void ResetJump()
{
readyToJump = true;
}
private float desiredX;
private void Look()
{
float mouseX = Input.GetAxis("Mouse X") * sensitivity * Time.fixedDeltaTime * sensMultiplier;
float mouseY = Input.GetAxis("Mouse Y") * sensitivity * Time.fixedDeltaTime * sensMultiplier;
//Find current look rotation
Vector3 rot = playerCam.transform.localRotation.eulerAngles;
desiredX = rot.y + mouseX;
//Rotate, and also make sure we dont over- or under-rotate.
xRotation -= mouseY;
float clamp = 89.5f;
xRotation = Mathf.Clamp(xRotation, -clamp, clamp);
//Perform the rotations
playerCam.transform.localRotation = Quaternion.Euler(xRotation, desiredX, 0);
orientation.transform.localRotation = Quaternion.Euler(0, desiredX, 0);
}
private void CounterMovement(float x, float y, Vector2 mag)
{
if (!grounded || jumping) return;
//Slow down sliding
if (crouching)
{
rb.AddForce(moveSpeed * Time.deltaTime * -rb.velocity.normalized * slideCounterMovement);
return;
}
//Counter movement
if (Math.Abs(mag.x) > threshold && Math.Abs(x) < 0.05f || (mag.x < -threshold && x > 0) || (mag.x > threshold && x < 0))
{
rb.AddForce(moveSpeed * orientation.transform.right * Time.deltaTime * -mag.x * counterMovement);
}
if (Math.Abs(mag.y) > threshold && Math.Abs(y) < 0.05f || (mag.y < -threshold && y > 0) || (mag.y > threshold && y < 0))
{
rb.AddForce(moveSpeed * orientation.transform.forward * Time.deltaTime * -mag.y * counterMovement);
}
//Limit diagonal running. This will also cause a full stop if sliding fast and un-crouching, so not optimal.
if (Mathf.Sqrt((Mathf.Pow(rb.velocity.x, 2) + Mathf.Pow(rb.velocity.z, 2))) > maxSpeed)
{
float fallspeed = rb.velocity.y;
Vector3 n = rb.velocity.normalized * maxSpeed;
rb.velocity = new Vector3(n.x, fallspeed, n.z);
}
}
/// <summary>
/// Find the velocity relative to where the player is looking
/// Useful for vectors calculations regarding movement and limiting movement
/// </summary>
/// <returns></returns>
public Vector2 FindVelRelativeToLook()
{
float lookAngle = orientation.transform.eulerAngles.y;
float moveAngle = Mathf.Atan2(rb.velocity.x, rb.velocity.z) * Mathf.Rad2Deg;
float u = Mathf.DeltaAngle(lookAngle, moveAngle);
float v = 90 - u;
float magnitue = rb.velocity.magnitude;
float yMag = magnitue * Mathf.Cos(u * Mathf.Deg2Rad);
float xMag = magnitue * Mathf.Cos(v * Mathf.Deg2Rad);
return new Vector2(xMag, yMag);
}
//a lot of math (dont touch)
private void FindWallRunRotation()
{
if (!isWallRunning)
{
wallRunRotation = 0f;
return;
}
_ = new Vector3(0f, playerCam.transform.rotation.y, 0f).normalized;
new Vector3(0f, 0f, 1f);
float num = 0f;
float current = playerCam.transform.rotation.eulerAngles.y;
if (Math.Abs(wallNormalVector.x - 1f) < 0.1f)
{
num = 90f;
}
else if (Math.Abs(wallNormalVector.x - -1f) < 0.1f)
{
num = 270f;
}
else if (Math.Abs(wallNormalVector.z - 1f) < 0.1f)
{
num = 0f;
}
else if (Math.Abs(wallNormalVector.z - -1f) < 0.1f)
{
num = 180f;
}
num = Vector3.SignedAngle(new Vector3(0f, 0f, 1f), wallNormalVector, Vector3.up);
float num2 = Mathf.DeltaAngle(current, num);
wallRunRotation = (0f - num2 / 90f) * wallRunRotateAmount;
if (!useWallrunning)
{
return;
}
if ((Mathf.Abs(wallRunRotation) < 4f && y > 0f && Math.Abs(x) < 0.1f) || (Mathf.Abs(wallRunRotation) > 22f && y < 0f && Math.Abs(x) < 0.1f))
{
if (!cancelling)
{
cancelling = true;
CancelInvoke("CancelWallrun");
Invoke("CancelWallrun", 0.2f);
}
}
else
{
cancelling = false;
CancelInvoke("CancelWallrun");
}
}
private bool IsFloor(Vector3 v)
{
return Vector3.Angle(Vector3.up, v) < maxSlopeAngle;
}
private bool IsSurf(Vector3 v)
{
float num = Vector3.Angle(Vector3.up, v);
if (num < 89f)
{
return num > maxSlopeAngle;
}
return false;
}
private bool IsWall(Vector3 v)
{
return Math.Abs(90f - Vector3.Angle(Vector3.up, v)) < 0.05f;
}
private bool IsRoof(Vector3 v)
{
return v.y == -1f;
}
/// <summary>
/// Handle ground detection
/// </summary>
private void OnCollisionStay(Collision other)
{
int layer = other.gameObject.layer;
if ((int)whatIsGround != ((int)whatIsGround | (1 << layer)))
{
return;
}
for (int i = 0; i < other.contactCount; i++)
{
Vector3 normal = other.contacts[i].normal;
if (IsFloor(normal))
{
if (isWallRunning)
{
isWallRunning = false;
}
grounded = true;
normalVector = normal;
cancellingGrounded = false;
CancelInvoke("StopGrounded");
}
if (IsWall(normal) && (layer == (int)whatIsGround || (int)whatIsGround == -1 || layer == LayerMask.NameToLayer("Ground") || layer == LayerMask.NameToLayer("ground"))) //seriously what is this
{
StartWallRun(normal);
onWall = true;
cancellingWall = false;
CancelInvoke("StopWall");
}
if (IsSurf(normal))
{
surfing = true;
cancellingSurf = false;
CancelInvoke("StopSurf");
}
IsRoof(normal);
}
float num = 3f;
if (!cancellingGrounded)
{
cancellingGrounded = true;
Invoke("StopGrounded", Time.deltaTime * num);
}
if (!cancellingWall)
{
cancellingWall = true;
Invoke("StopWall", Time.deltaTime * num);
}
if (!cancellingSurf)
{
cancellingSurf = true;
Invoke("StopSurf", Time.deltaTime * num);
}
}
private void StopGrounded()
{
grounded = false;
}
private void StopWall()
{
onWall = false;
isWallRunning = false;
}
private void StopSurf()
{
surfing = false;
}
//wallrunning functions
private void CancelWallrun()
{
//for when we want to stop wallrunning
MonoBehaviour.print("cancelled wallrun");
Invoke("GetReadyToWallrun", 0.1f);
rb.AddForce(wallNormalVector * escapeForce);
isWallRunning = false;
}
private void StartWallRun(Vector3 normal)
{
MonoBehaviour.print("wallrunning");
//cancels all y momentum and then applies an upwards force.
if (!grounded && useWallrunning)
{
wallNormalVector = normal;
if (!isWallRunning)
{
rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
rb.AddForce(Vector3.up * initialForce, ForceMode.Impulse);
}
isWallRunning = true;
}
}
private void WallRunning()
{
//checks if the wallrunning bool is set to true and if it is then applies
//a force to counter gravity enough to make it feel like wallrunning
if (isWallRunning)
{
rb.AddForce(-wallNormalVector * Time.deltaTime * moveSpeed);
rb.AddForce(Vector3.up * Time.deltaTime * rb.mass * 40f * wallRunGravity * -Physics.gravity.y);
}
}
}
I used a addForce funktion to add the recoil.Please help me.
This sentence is juist written because i need to add more details
For example there are 5 target and they are moving randomly around the turret.
Now i'm using only one target targets[0] and the turret is rotating facing the target and shoot laser to it.
Now i want to make it with multiple targets and that the turret will choose each time the closet target and will shoot to it the laser.
I changed this part added a for loop over the targets :
for (int i = 0; i < targets.Count; i++)
but i'm still using only one target, targets[0] i'm not sure how to add the distance part and the closet target choosing.
I tried this solution but now the turret(transform) is not rotating at all towards the selected target. for some reason this two lines return null on the closestTarget :
RotateToMouseDirection(gameObject, closestTarget.position);
The script with the changes :
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System;
using UnityEngine;
public class Hovl_DemoLasers : MonoBehaviour
{
public List<Transform> targets;
public GameObject FirePoint;
public Camera Cam;
public float MaxLength;
public GameObject[] Prefabs;
private Ray RayMouse;
private Vector3 direction;
private Quaternion rotation;
[Header("GUI")]
private float windowDpi;
private int Prefab;
private GameObject Instance;
private Hovl_Laser LaserScript;
private Hovl_Laser2 LaserScript2;
private bool rotateMouse = true;
private bool startLaser = true;
private float buttonSaver = 0f;
private Hovl_LaserDemo hovl_laserDemo;
private float maxDistance = 0;
private float distance;
private Transform closestTarget;
void Start ()
{
if (Screen.dpi < 1) windowDpi = 1;
if (Screen.dpi < 200) windowDpi = 1;
else windowDpi = Screen.dpi / 200f;
Counter(0);
}
void Update()
{
//Enable lazer
if (Input.GetMouseButtonDown(0))
{
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
rotateMouse = true;
}
if (Input.GetMouseButtonDown(1))
{
rotateMouse = false;
}
//Disable lazer prefab
if (Input.GetMouseButtonUp(0))
{
/*if (LaserScript) LaserScript.DisablePrepare();
if (LaserScript2) LaserScript2.DisablePrepare();
Destroy(Instance,1);*/
}
if ((Input.GetKey(KeyCode.A) || Input.GetAxis("Horizontal") < 0) && buttonSaver >= 0.4f)// left button
{
buttonSaver = 0f;
Counter(-1);
}
if ((Input.GetKey(KeyCode.D) || Input.GetAxis("Horizontal") > 0) && buttonSaver >= 0.4f)// right button
{
buttonSaver = 0f;
Counter(+1);
}
buttonSaver += Time.deltaTime;
if (startLaser)
{
rotateMouse = false;
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
hovl_laserDemo = Instance.GetComponent<Hovl_LaserDemo>();
startLaser = false;
}
if (targets != null)
{
for (int i = 0; i < targets.Count; i++)
{
distance = Vector3.Distance(transform.position, targets[i].position);
if (distance < maxDistance)
{
maxDistance = distance;
closestTarget = targets[i];
}
}
if (hovl_laserDemo != null)
{
MaxLength = distance;
hovl_laserDemo.MaxLength = distance;
}
if (Cam != null)
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, MaxLength))
{
RotateToMouseDirection(gameObject, closestTarget.position);
}
else
{
RotateToMouseDirection(gameObject, closestTarget.position);
}
}
}
if (Cam != null && rotateMouse)
{
RaycastHit hit;
var mousePos = Input.mousePosition;
RayMouse = Cam.ScreenPointToRay(mousePos);
if (Physics.Raycast(RayMouse.origin, RayMouse.direction, out hit, MaxLength))
{
RotateToMouseDirection(gameObject, hit.point);
}
else
{
var pos = RayMouse.GetPoint(MaxLength);
RotateToMouseDirection(gameObject, pos);
}
}
else
{
Debug.Log("No camera");
}
}
void OnGUI()
{
GUI.Label(new Rect(10 * windowDpi, 5 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use the keyboard buttons A/<- and D/-> to change lazers!");
GUI.Label(new Rect(10 * windowDpi, 20 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use left mouse button for shooting!");
}
void Counter(int count)
{
Prefab += count;
if (Prefab > Prefabs.Length - 1)
{
Prefab = 0;
}
else if (Prefab < 0)
{
Prefab = Prefabs.Length - 1;
}
}
void RotateToMouseDirection (GameObject obj, Vector3 destination)
{
direction = destination - obj.transform.position;
rotation = Quaternion.LookRotation(direction);
obj.transform.localRotation = Quaternion.Lerp(obj.transform.rotation, rotation, 1);
}
}
The old original script before the changes :
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System;
using UnityEngine;
public class DemoLasers : MonoBehaviour
{
public List<Transform> targets;
public GameObject FirePoint;
public Camera Cam;
public float MaxLength;
public GameObject[] Prefabs;
private Ray RayMouse;
private Vector3 direction;
private Quaternion rotation;
[Header("GUI")]
private float windowDpi;
private int Prefab;
private GameObject Instance;
private Hovl_Laser LaserScript;
private Hovl_Laser2 LaserScript2;
private bool rotateMouse = true;
private bool startLaser = true;
private float buttonSaver = 0f;
private Hovl_LaserDemo hovl_laserDemo;
void Start ()
{
if (Screen.dpi < 1) windowDpi = 1;
if (Screen.dpi < 200) windowDpi = 1;
else windowDpi = Screen.dpi / 200f;
Counter(0);
}
void Update()
{
//Enable lazer
if (Input.GetMouseButtonDown(0))
{
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
rotateMouse = true;
}
if (Input.GetMouseButtonDown(1))
{
rotateMouse = false;
}
if ((Input.GetKey(KeyCode.A) || Input.GetAxis("Horizontal") < 0) && buttonSaver >= 0.4f)// left button
{
buttonSaver = 0f;
Counter(-1);
}
if ((Input.GetKey(KeyCode.D) || Input.GetAxis("Horizontal") > 0) && buttonSaver >= 0.4f)// right button
{
buttonSaver = 0f;
Counter(+1);
}
buttonSaver += Time.deltaTime;
if (startLaser)
{
rotateMouse = false;
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
hovl_laserDemo = Instance.GetComponent<Hovl_LaserDemo>();
startLaser = false;
}
if (targets != null)
{
for (int i = 0; i < targets.Count; i++)
{
if (hovl_laserDemo != null)
{
float distance = Vector3.Distance(gameObject.transform.position, targets[0].position);
MaxLength = distance;
hovl_laserDemo.MaxLength = distance;
}
if (Cam != null)
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, MaxLength))
{
RotateToMouseDirection(gameObject, targets[0].position);
}
else
{
RotateToMouseDirection(gameObject, targets[0].position);
}
}
}
}
if (Cam != null && rotateMouse)
{
RaycastHit hit;
var mousePos = Input.mousePosition;
RayMouse = Cam.ScreenPointToRay(mousePos);
if (Physics.Raycast(RayMouse.origin, RayMouse.direction, out hit, MaxLength))
{
RotateToMouseDirection(gameObject, hit.point);
}
else
{
var pos = RayMouse.GetPoint(MaxLength);
RotateToMouseDirection(gameObject, pos);
}
}
else
{
Debug.Log("No camera");
}
}
void OnGUI()
{
GUI.Label(new Rect(10 * windowDpi, 5 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use the keyboard buttons A/<- and D/-> to change lazers!");
GUI.Label(new Rect(10 * windowDpi, 20 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use left mouse button for shooting!");
}
void Counter(int count)
{
Prefab += count;
if (Prefab > Prefabs.Length - 1)
{
Prefab = 0;
}
else if (Prefab < 0)
{
Prefab = Prefabs.Length - 1;
}
}
void RotateToMouseDirection (GameObject obj, Vector3 destination)
{
direction = destination - obj.transform.position;
rotation = Quaternion.LookRotation(direction);
obj.transform.localRotation = Quaternion.Lerp(obj.transform.rotation, rotation, 1);
}
}
Have 2 Variables in a Loop.
one is the index of the current closest target in you List,
and the other one the distance
int closestIndex = 0;
float maxDistance = 0;
for (int i = 0; i < targets.Count; i++)
{
//Here we calculate the distance of the current pos
//You can take any Formula e.g. the Manhattan Formula
float distance = Vector3.Distance(turretPositionOrSth, targets[i].position);
//if the distance is shorter than the current max Distance
if (distance < maxDistance)
{
maxDistance = distance;
closestIndex = i;
}
}
//Now you have your Index in the list to the closest Target,which you can use
//you can use now for example targets[closestIndex] for aiming or so
Also you don't need your already written loop anymore
Here's essentially the same answer as tthe one #cpaech gave, but there was a couple issues.
int closestIndex = 0;
float minDistance = float.MaxValue;
for (int i = 0; i < targets.Count; i++)
{
//Here we calculate the distance of the current pos
//You can take any Formula e.g. the Manhattan Formula
float distance = Vector3.Distance(turretPositionOrSth, targets[i].position);
//if the distance is shorter than the current max Distance
if (distance < maxDistance)
{
maxDistance = distance;
closestIndex = i;
}
}
It could also be helpful to have an attribute for the closest target and have
if (distance < maxDistance)
{
maxDistance = distance;
closestTarget = targets[i];
}
It looks like you have two requirements -- to find not just the closest enemy, but the closest enemy with direct line of sight to the turret?
You could sort the list of enemies by distance to the turret and iterate over it from closest to furthest until a valid target is found (requiring fewer raycasts might provide a small performance advantage if there were a massive number of enemies), or you could just try the raycast on every enemy, but here's a compromise that only tries the raycast if the enemy is closer than any previous enemy tested.
Transform target = null;
float lowestDistance = float.MaxValue;
if( cam != null && hovl_laserDemo != null && targets != null )
{
for( int i = 0; i < targets.Count; i++ )
{
float distance = Vector3.Distance(gameObject.transform.position, targets[i].position);
if( distance < lowestDistance )
{
RaycastHit hit;
if( Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, distance)
&& hit.transform == targets[i] )
{
// If our raycast successfully reached the intended target without being blocked by anything else
lowestDistance = distance;
target = targets[i];
}
}
}
}
if( target != null )
{
MaxLength = lowestDistance;
hovl_laserDemo.MaxLength = lowestDistance;
RotateToMouseDirection(gameObject, target.position);
}
else
{
// Do whatever you want to do when there is no valid target
}
Edit: Actually it looks like your raycast was succeeding if it hit anything, not just the intended target. I've tried to correct that above.
The goal is to use a time variable for example if the variable int value is 5 then each 5 seconds another object will start moving on the positions.
Now with the loop inside the Move method :
for (int i = 0; i < objectsToMove.Count; i++)
All the objects are moving at the same time but I want to make some kind of queue logic so each N seconds another object will start moving on the positions.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class MoveOnCurvedLines : MonoBehaviour
{
public LineRenderer lineRenderer;
public List<GameObject> objectsToMove = new List<GameObject>();
public float speed;
public bool go = false;
public bool moveToFirstPositionOnStart = false;
private Vector3[] positions;
private Vector3[] pos;
private int index = 0;
private bool goForward = true;
// Start is called before the first frame update
void Start()
{
objectsToMove = GameObject.FindGameObjectsWithTag("New Prefab").ToList();
pos = GetLinePointsInWorldSpace();
if (moveToFirstPositionOnStart == true)
{
objectsToMove[0].transform.position = pos[index];
}
}
Vector3[] GetLinePointsInWorldSpace()
{
positions = new Vector3[lineRenderer.positionCount];
//Get the positions which are shown in the inspector
lineRenderer.GetPositions(positions);
//the points returned are in world space
return positions;
}
// Update is called once per frame
void Update()
{
if (go == true)
{
Move();
}
}
void Move()
{
for (int i = 0; i < objectsToMove.Count; i++)
{
Vector3 newPos = objectsToMove[i].transform.position;
float distanceToTravel = speed * Time.deltaTime;
bool stillTraveling = true;
while (stillTraveling)
{
Vector3 oldPos = newPos;
newPos = Vector3.MoveTowards(oldPos, pos[index], distanceToTravel);
distanceToTravel -= Vector3.Distance(newPos, oldPos);
if (newPos == pos[index]) // Vector3 comparison is approximate so this is ok
{
// when you hit a waypoint:
if (goForward)
{
bool atLastOne = index >= pos.Length - 1;
if (!atLastOne) index++;
else { index--; goForward = false; }
}
else
{ // going backwards:
bool atFirstOne = index <= 0;
if (!atFirstOne) index--;
else { index++; goForward = true; }
}
}
else
{
stillTraveling = false;
}
}
objectsToMove[i].transform.position = newPos;
}
}
}
This is what I tried with InvokeRepeating :
Starting InvokeRepeating in the Start() and cancelled the Move() calling in the Update.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class MoveOnCurvedLines : MonoBehaviour
{
public LineRenderer lineRenderer;
public List<GameObject> objectsToMove = new List<GameObject>();
public float speed;
public bool go = false;
public bool moveToFirstPositionOnStart = false;
private Vector3[] positions;
private Vector3[] pos;
private int index = 0;
private bool goForward = true;
// Start is called before the first frame update
void Start()
{
objectsToMove = GameObject.FindGameObjectsWithTag("New Prefab").ToList();
pos = GetLinePointsInWorldSpace();
if (moveToFirstPositionOnStart == true)
{
objectsToMove[0].transform.position = pos[index];
}
InvokeRepeating("Move", 3f, 0.1f);
}
Vector3[] GetLinePointsInWorldSpace()
{
positions = new Vector3[lineRenderer.positionCount];
//Get the positions which are shown in the inspector
lineRenderer.GetPositions(positions);
//the points returned are in world space
return positions;
}
// Update is called once per frame
void Update()
{
if (go == true)
{
//Move();
}
}
void Move()
{
for (int i = 0; i < objectsToMove.Count; i++)
{
Vector3 newPos = objectsToMove[i].transform.position;
float distanceToTravel = speed * Time.deltaTime;
bool stillTraveling = true;
while (stillTraveling)
{
Vector3 oldPos = newPos;
newPos = Vector3.MoveTowards(oldPos, pos[index], distanceToTravel);
distanceToTravel -= Vector3.Distance(newPos, oldPos);
if (newPos == pos[index]) // Vector3 comparison is approximate so this is ok
{
// when you hit a waypoint:
if (goForward)
{
bool atLastOne = index >= pos.Length - 1;
if (!atLastOne) index++;
else { index--; goForward = false; }
}
else
{ // going backwards:
bool atFirstOne = index <= 0;
if (!atFirstOne) index--;
else { index++; goForward = true; }
}
}
else
{
stillTraveling = false;
}
}
objectsToMove[i].transform.position = newPos;
}
}
}
int i = 0;
void StartMove()
{
i = 0;
InvokeRepeating(nameof(Move), 3f, 0.1f);
}
void Move()
{
if( i < objectsToMove.Count)
{
Vector3 newPos = objectsToMove[i].transform.position;
float distanceToTravel = speed * Time.deltaTime;
bool stillTraveling = true;
while (stillTraveling)
{
Vector3 oldPos = newPos;
newPos = Vector3.MoveTowards(oldPos, pos[index], distanceToTravel);
distanceToTravel -= Vector3.Distance(newPos, oldPos);
if (newPos == pos[index]) // Vector3 comparison is approximate so this is ok
{
// when you hit a waypoint:
if (goForward)
{
bool atLastOne = index >= pos.Length - 1;
if (!atLastOne) index++;
else { index--; goForward = false; }
}
else
{ // going backwards:
bool atFirstOne = index <= 0;
if (!atFirstOne) index--;
else { index++; goForward = true; }
}
}
else
{
stillTraveling = false;
}
}
objectsToMove[i].transform.position = newPos;
i++;
}
}
Try this one might help you. Here What I did is to remove the for() loop and instead use an if() condition this way You move function will only execute one time only for one object each time Move() get called by InvokeRepeating(). Nove Call StartMove() where/when you want to start moving the objects.
I have 3 scripts attached to a camera I called Fly Camera.
A bit long but all 3 scripts are working together:
First the script LookAtCamera:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LookAtCamera : MonoBehaviour
{
//values that will be set in the Inspector
public Transform target;
public float RotationSpeed;
//values for internal use
private Quaternion _lookRotation;
private Vector3 _direction;
// Update is called once per frame
void Update()
{
//find the vector pointing from our position to the target
if (target)
_direction = (target.position - transform.position).normalized;
//create the rotation we need to be in to look at the target
if (_direction != Vector3.zero)
_lookRotation = Quaternion.LookRotation(_direction);
//rotate us over time according to speed until we are in the required rotation
transform.rotation = Quaternion.Slerp(transform.rotation, _lookRotation, Time.deltaTime * RotationSpeed);
}
}
Next FlyToOverTerrain:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FlyToOverTerrain : MonoBehaviour
{
public Transform target;
public float desiredHeight = 10f;
public float flightSmoothTime = 10f;
public float maxFlightspeed = 10f;
public float flightAcceleration = 1f;
public float levelingSmoothTime = 0.5f;
public float maxLevelingSpeed = 10000f;
public float levelingAcceleration = 2f;
private Vector3 flightVelocity = Vector3.zero;
private float heightVelocity = 0f;
private void LateUpdate()
{
Vector3 position = transform.position;
float currentHeight = position.y;
if (target && flightAcceleration > float.Epsilon)
{
position = Vector3.SmoothDamp(position, target.position, ref flightVelocity, flightSmoothTime / flightAcceleration, maxFlightspeed, flightAcceleration * Time.deltaTime);
}
if (levelingAcceleration > float.Epsilon)
{
float targetHeight = Terrain.activeTerrain.SampleHeight(position) + desiredHeight;
position.y = Mathf.SmoothDamp(currentHeight, targetHeight, ref heightVelocity, levelingSmoothTime / levelingAcceleration, maxLevelingSpeed, levelingAcceleration * Time.deltaTime);
}
transform.position = position;
}
}
And last PatrolOverTerrain:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class PatrolData
{
public Transform target = null;
public float minDistance = 5f;
public float lingerDuration = 5f;
public float desiredHeight = 10f;
public float flightSmoothTime = 10f;
public float maxFlightspeed = 10f;
public float flightAcceleration = 1f;
public float levelingSmoothTime = 0.5f;
public float maxLevelingSpeed = 10000f;
public float levelingAcceleration = 2f;
}
public class PatrolOverTerrain : MonoBehaviour
{
public FlyToOverTerrain flyOverTerrain;
public LookAtCamera lookAtCamera;
public enum PatrolMode { Clamp, Wrap, PingPong };
public PatrolData[] patrolPoints;
public PatrolMode mode = PatrolMode.Wrap;
private int iterator = 0;
private int index = 0;
private float lingerDuration = 0f;
private int overallLength = 0;
public bool autoFreedomPatrol = false;
public List<GameObject> Targets = new List<GameObject>();
public string tagName;
public Vector3 distanceFromTarget;
public void Start()
{
if (tagName != "")
{
GameObject[] tempObj = GameObject.FindGameObjectsWithTag(tagName);
for (int i = 0; i < tempObj.Length; i++)
{
//Add to list only if it does not exist
if (!Targets.Contains(tempObj[i]))
{
Targets.Add(tempObj[i]);
}
}
//Get the current Size
if (tempObj != null)
{
overallLength = Targets.Count;
}
GeneratePatrolPoints();
}
}
private void OnEnable()
{
if (patrolPoints.Length > 0)
{
lingerDuration = patrolPoints[index].lingerDuration;
}
}
private void Update()
{
int length = patrolPoints.Length;
if (!flyOverTerrain) return;
if (patrolPoints.Length < 1) return;
if (index < 0) return;
var patrol = patrolPoints[index];
if (lingerDuration <= 0)
{
iterator++;
switch (mode)
{
case PatrolMode.Clamp:
index = (iterator >= length) ? -1 : iterator;
break;
case PatrolMode.Wrap:
iterator = Modulus(iterator, length);
index = iterator;
break;
case PatrolMode.PingPong:
index = PingPong(iterator, length);
break;
}
if (index < 0) return;
patrol = patrolPoints[index];
flyOverTerrain.target = patrol.target;
flyOverTerrain.desiredHeight = patrol.desiredHeight;
flyOverTerrain.flightSmoothTime = patrol.flightSmoothTime;
flyOverTerrain.maxFlightspeed = patrol.maxFlightspeed;
flyOverTerrain.flightAcceleration = patrol.flightAcceleration;
flyOverTerrain.levelingSmoothTime = patrol.levelingSmoothTime;
flyOverTerrain.maxLevelingSpeed = patrol.maxLevelingSpeed;
flyOverTerrain.levelingAcceleration = patrol.levelingAcceleration;
lookAtCamera.target = patrol.target;
lookAtCamera.RotationSpeed = 3;
lingerDuration = patrolPoints[index].lingerDuration;
}
Vector3 targetOffset = Vector3.zero;
if ((bool)patrol.target)
{
targetOffset = transform.position - patrol.target.position;
}
float sqrDistance = patrol.minDistance * patrol.minDistance;
if (targetOffset.sqrMagnitude <= sqrDistance)
{
flyOverTerrain.target = null;
lookAtCamera.target = null;
lingerDuration -= Time.deltaTime;
}
else
{
flyOverTerrain.target = patrol.target;
lookAtCamera.target = patrol.target;
}
distanceFromTarget = transform.position - patrol.target.position;
}
private int PingPong(int baseNumber, int limit)
{
if (limit < 2) return 0;
return limit - Mathf.Abs(limit - Modulus(baseNumber, limit + (limit - 2)) - 1) - 1;
}
private int Modulus(int baseNumber, int modulus)
{
return (modulus == 0) ? baseNumber : baseNumber - modulus * (int)Mathf.Floor(baseNumber / (float)modulus);
}
public void GeneratePatrolPoints()
{
patrolPoints = new PatrolData[Targets.Count];
for (int i = 0; i < patrolPoints.Length; i++)
{
patrolPoints[i] = new PatrolData();
patrolPoints[i].target = Targets[i].transform;
patrolPoints[i].minDistance = 30f;
patrolPoints[i].lingerDuration = 3f;
patrolPoints[i].desiredHeight = 20f;
patrolPoints[i].flightSmoothTime = 10f;
patrolPoints[i].maxFlightspeed = 10f;
patrolPoints[i].flightAcceleration = 3f;
patrolPoints[i].levelingSmoothTime = 0.5f;
patrolPoints[i].maxLevelingSpeed = 10000f;
patrolPoints[i].levelingAcceleration = 2f;
}
}
}
The camera rotate facing the first waypoint but never move to the next one/s.
There are 4 Spheres as waypoints they are tagged as Target.
When running the game the camera rotate smooth slowly facing the first Sphere move to it but then stop there and never continue. It should move between all the Spheres and then start over again.
I think the issue is in
if (targetOffset.sqrMagnitude <= sqrDistance)
{
flyOverTerrain.target = null;
lookAtCamera.target = null;
lingerDuration -= Time.deltaTime;
}
else
{
flyOverTerrain.target = patrol.target;
lookAtCamera.target = patrol.target;
}
You only reduce the lingerDuration once namely the frame you reach the first target.
So your
if (lingerDuration <= 0)
will probably never match.
I guess you rather want to reducer it in every frame the Update runs so rather move it outside that block.
I'ld also suggest to rather use
if(Vector3.Distance(transform.position, patrol.target.position) <= patrol.minDistance)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AnimatorController : MonoBehaviour
{
public Animator[] animators;
public Transform target;
public float speed = 1f;
public float rotationSpeed;
public bool slowDown = false;
public PlayAnimations playanimation;
private bool endRot = false;
private bool endRotation = false;
private Vector3 center;
private bool StartWaitingAnim = true;
// Use this for initialization
void Start()
{
center = target.GetComponent<Renderer>().bounds.center;
for (int i = 0; i < animators.Length; i++)
{
animators[i].SetFloat("Walking Speed", speed);
}
}
// Update is called once per frame
void Update()
{
float distanceFromTarget = Vector3.Distance(animators[2].transform.position, target.position);
for (int i = 0; i < animators.Length; i++)
{
animators[2].transform.position = Vector3.MoveTowards(animators[2].transform.position, center, 0);
}
if (slowDown)
{
if (distanceFromTarget < 10)
{
float speed = (distanceFromTarget / 10) / 1;
for (int i = 0; i < animators.Length; i++)
{
animators[i].SetFloat("Walking Speed", speed);
}
}
}
if (distanceFromTarget < 5f)
{
for (int i = 0; i < animators.Length; i++)
{
animators[i].SetBool("Idle", true);
if (StartWaitingAnim == true)
{
StartCoroutine(WaitForAnimation());
StartWaitingAnim = false;
}
RotateCharacters(2);
}
if (!endRot)
{
Quaternion goalRotation = Quaternion.Euler(0f, 180f, 0f);
float angleToGoal = Quaternion.Angle(
goalRotation,
animators[0].transform.localRotation);
float angleThisFrame = Mathf.Min(angleToGoal, rotationSpeed * Time.deltaTime);
// use axis of Vector3.down to keep angles positive for ease of use
animators[0].transform.Rotate(Vector3.up, angleThisFrame);
animators[1].transform.Rotate(Vector3.down, angleThisFrame);
// We end if we rotated the remaining amount.
endRot = (angleThisFrame == angleToGoal);
}
{
animators[0].SetBool("Rifle Aiming Idle", true);
animators[1].SetBool("Rifle Aiming Idle", true);
}
}
}
private void RotateCharacters(int CharacterIndexToRotate)
{
if (!endRotation && waitangimation == true)
{
Quaternion goalRotation = Quaternion.Euler(0f, -90f, 0f);
float angleToGoal = Quaternion.Angle(
goalRotation,
animators[CharacterIndexToRotate].transform.localRotation);
float angleThisFrame = Mathf.Min(angleToGoal, 100 * Time.deltaTime);
animators[CharacterIndexToRotate].transform.Rotate(Vector3.down, angleThisFrame);
endRotation = (angleThisFrame == angleToGoal);
}
else
{
animators[2].SetBool("Magic Pack", true);
}
}
bool waitangimation = false;
IEnumerator WaitForAnimation()
{
yield return new WaitForSeconds(3);
waitangimation = true;
}
}
When using to rotate the first two animators inside Update when checking:
if (!endRot)
Then both animators 0 and 1 are rotating slowly smooth.
But then I wanted to make a method for rotating and called it RotateCharacters
This this method I'm trying to rotate animators[2] but he is rotating very fast too fast. And the code inside RotateCharacters is the same for rotating the other animators. But still animators[2] is rotating very fast.
In the end I will want to stay only with the method RotateCharacters for rotating the animators.
You call RotateCharacters with 2 as parameter as opposed to the loop variable i.
So you rotate animators[2] in every loop-iteration.