Bullet rotation unwanted offset Unity - c#

I'm trying to have an enemy circle the player and shoot bullets at said player. Whenever the enemy shoots though, the bullet is slightly off from the player and continues to shoot further from the players position.
this is the enemies behaviour
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CirclingScript : MonoBehaviour, IPooledObject
{
public Transform tf;
public Transform Target;
public GameObject Ship;
public GameObject WaveMaker;
public EnemyScript enemyscript;
public string BulletName;
ObjectPools objectPooler;
private int I; // Wave number
public int BulletAmount;
public float angle;
public float Radius;
public float RotateSpeed;
private float Timer;
public float Health;
private Quaternion BulletRot;
public void OnObjectSpawn()
{
WaveMaker = GameObject.Find("EnemyWaveMaker");//gets the game object
enemyscript = WaveMaker.GetComponent<EnemyScript>();// gets the scripts for the wave makers
I = enemyscript.i;
Ship = GameObject.Find("Ship");//gets the game object
Target = Ship.GetComponent<Transform>();// gets the Transform
//https://answers.unity.com/questions/1068513/place-8-objects-around-a-target-gameobject.html thank you ^-^
angle = enemyscript.RotSpace * Mathf.PI * 2f / enemyscript.Waves[I].Amount;
RotateSpeed = enemyscript.Waves[I].RotateSpeed;
Radius = enemyscript.Waves[I].Radius;
}
void Start()
{
objectPooler = ObjectPools.Instance;
}
void OnTriggerEnter2D(Collider2D coll)
{
if (coll.gameObject.CompareTag("Bullet"))
{
Health -= coll.GetComponent<DamageScript>().Damage;
}
if (Health <= 0)
{
objectPooler.SpawnFromPool("Boom", tf.position, Quaternion.identity);
gameObject.SetActive(false);
}
}
// Update is called once per frame
void Update()
{
angle += RotateSpeed * Time.deltaTime;
Timer += Time.deltaTime;
Vector2 offset = new Vector2(Mathf.Sin(angle), Mathf.Cos(angle)) * Radius;
tf.position = (Vector2)Target.position + offset;
if (Timer >= 2f)
{
Vector3 difference = Target.position - tf.position;
float rotationZ = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
BulletPatternsModule.ShootArc(angle, BulletAmount, BulletName, tf, rotationZ);
Timer = 0f;
}
}
}
and the code for shooting the bullets
public static void ShootArc(float ArcSize, int BulletAmount, string BulletName, Transform tf, float Offset)//All arcs are in angles, not radians
{
float angle = 0;
angle = Offset;//Offset is to the left
for (int i = 0; i < BulletAmount; i++)
{
float AngleStep = ArcSize / BulletAmount;//Gets the step size for arc
angle += AngleStep;
objectPooler.SpawnFromPool(BulletName, tf.position, Quaternion.Euler(0, 0, angle));//Shoots the bullet
}
}
The offset makes the enemies near useless
Any help would be appreciated :)
(more text in order for me to post the question. Isn't this fun?)

It will be easier to make the enemy look at the player using this function
transform.LookAt(target.position);

Related

Unity player movement on moving planet

I am making a game involving orbital physics. I was successfully able to implement this with a slightly modified version of Brackeys gravity tutorial https://youtu.be/Ouu3D_VHx9o, this is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class gravity : MonoBehaviour
{
public GameObject self;
public Rigidbody rb;
public Vector3 initialVelocity;
const float G = 66.74f;
public static List<gravity> Attractors;
public bool isAttractable;
private void Awake()
{
rb.AddForce(initialVelocity);
}
private void FixedUpdate()
{
//planets
if (isAttractable == false)
{
foreach (gravity attractor in Attractors)
{
if (attractor != this)
Attract(attractor);
}
}
//players, spaceships, astroids, ect
if (isAttractable == true)
{
foreach (gravity attractor in Attractors)
{
if (attractor != this)
Attract(attractor);
}
}
}
void OnEnable()
{
if( isAttractable == false)
{
if (Attractors == null)
Attractors = new List<gravity>();
Attractors.Add(this);
}
}
void OnDisable()
{
if (isAttractable == false)
{
Attractors.Remove(this);
}
}
void Attract(gravity objToAttract)
{
Rigidbody rbToAttract = objToAttract.rb;
Vector3 direction = -1 * (rb.position - rbToAttract.position);
Vector3 Force = direction.normalized * (G * ((rb.mass * rbToAttract.mass) / direction.sqrMagnitude));
rb.AddForce(Force);
}
public GameObject GetClosestPlanet()
{
GameObject close = null;
float minDist = Mathf.Infinity;
foreach (gravity attracor in Attractors)
{
float dist = Vector3.Distance(attracor.transform.position, transform.position);
if (dist < minDist)
{
close = attracor.transform.gameObject;
minDist = dist;
}
}
return close;
}
}
Then for player movement I used (and modified) Sebastian Lagues tutorial https://youtu.be/TicipSVT-T8,
this resulted in this code for the player controller:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerController : MonoBehaviour
{
public float mouseSensitivityX = 250f;
public float mouseSensitivityY = 250f;
Transform cameraT;
float verticalLookRot;
private Rigidbody rb;
Vector3 moveAmount;
Vector3 smootgMoveVelocity;
public float moveSpeed = 15;
public float jumpForce = 220;
public LayerMask groundedMask;
public bool grounded;
public GameObject currentPlanet;
private gravity playerGravity;
private void Awake()
{
rb = GetComponent<Rigidbody>();
playerGravity = GetComponent<gravity>();
Cursor.lockState = CursorLockMode.Locked;
cameraT = Camera.main.transform;
}
void Update()
{
currentPlanet = playerGravity.GetClosestPlanet();
//camera
transform.Rotate(Vector3.up * Input.GetAxis("Mouse X") * Time.deltaTime * mouseSensitivityX);
verticalLookRot += Input.GetAxis("Mouse Y") * Time.deltaTime * mouseSensitivityY;
verticalLookRot = Mathf.Clamp(verticalLookRot, -60, 60);
cameraT.localEulerAngles = Vector3.left * verticalLookRot;
//move input
Vector3 moveDir = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")).normalized;
Vector3 targetMoveAmount = moveDir * moveSpeed;
moveAmount = Vector3.SmoothDamp(targetMoveAmount, targetMoveAmount, ref smootgMoveVelocity, .15f);
//level on planet
if(currentPlanet != null)
{
transform.rotation = Quaternion.FromToRotation(transform.up, (transform.position - currentPlanet.transform.position).normalized) * transform.rotation;
}
//jump
if (Input.GetButtonDown("Jump"))
{ if(grounded)
{
rb.AddForce(transform.up * jumpForce);
print("u jumped");
}
}
}
private void FixedUpdate()
{
//move
rb.MovePosition(rb.position + transform.TransformDirection(moveAmount) * Time.fixedDeltaTime);
//check if on ground
Ray ray = new Ray(transform.position, -transform.up);
RaycastHit hit;
grounded = Physics.Raycast(ray, out hit, transform.localScale.y + 1.1f, groundedMask);
}
}
Now for the issue, this systems works fine when the planet the player is walking on is stationary. As in there are no other attracting bodys in the system and the planet has no initial velocity. However if the planet is moving the player will bounce up and down uncontrollably and will not be able to walk a certain distance away from the planets farthest point from its direction of movement. Here is a recording of this: https://youtu.be/noMekosb7CU
Does anyone know what is causing the bouncing and walking restrictions and how I can fix it?
Some notes on suggested solutions that haven't worked:
-set the planet as the players parent object, same results
-increase players mass, same results
-set the players velocity to += the planets velocity, same results or player goes into infinity
For me it seems to be working "correctly".
Looking like your player is attracted correctly and when the planet moves, your player is quickly moving towards the planet.
I think you could temporarily assign the player as a child gameobject to the planet he's walking on and he should probably move correctly along the planet coordinates and not on global coordinates. (If it works, you could just always assign the player as a child gameObject to every new planet that he visits)

Unity limit rigidbody velocity in specific direction with addforce?

I am creating a third person player movement script. The movement adds force to the rigidbody relative to the direction of the camera. I want to have a max speed limit in the forward direction (cForward), and a separate max speed limit for the horizontal/right direction (cRight). Normally I would be fine with setting the velocity directly, however this screws up gravity for the player. Is there any way to achieve this by using addforce OR is there a way to get gravity working properly when setting velocity directly? Here is what I have so far(some of my other attempts at a solution are commented out):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public Camera mainCamera;
public float horizontalWalkSpeed = 500.0f;
public float verticalWalkSpeed = 500.0f;
public float horizontalSprintSpeed = 1000.0f;
public float verticalSprintSpeed = 1000.0f;
public bool isSprinting = false;
public bool cannotMove = false;
public float accelerationSpeed = 0.2f;
private Rigidbody pRigidBody;
private Vector2 currentInputVector;
private Vector2 smoothInputVelocity;
// Start is called before the first frame update
void Start()
{
pRigidBody = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
HandleInput();
}
private void FixedUpdate()
{
Vector3 cForward = mainCamera.transform.forward;
Vector3 cRight = mainCamera.transform.right;
cForward.y = 0.0f;
cRight.y = 0.0f;
cForward.Normalize();
cRight.Normalize();
if (!cannotMove && !isSprinting)
{
Vector3 vForce = cForward * currentInputVector.y * verticalWalkSpeed;
Vector3 hForce = cRight * currentInputVector.x * horizontalWalkSpeed;
//Vector3 gravity = Vector3.up * -9.8f;
Vector3 force = vForce + hForce;
//float verSpeed = Vector3.Dot(pRigidBody.velocity, cForward);
//float horSpeed = Vector3.Dot(pRigidBody.velocity, cRight);
//if (verSpeed >= 0 && verSpeed <= verticalWalkSpeed)
//{
// pRigidBody.AddForce(vForce, ForceMode.VelocityChange);
//}
//if(horSpeed < horizontalWalkSpeed)
//{
// pRigidBody.AddForce(hForce, ForceMode.VelocityChange);
//}
//float velocityInDirection = Vector3.Dot(pRigidBody.velocity, cForward);
//if(velocityInDirection > verticalWalkSpeed)
//{
// pRigidBody.AddForce(-vForce, ForceMode.VelocityChange);
//}
//pRigidBody.velocity = force;
pRigidBody.AddForce(force, ForceMode.VelocityChange);
}
else if (!cannotMove && isSprinting)
{
pRigidBody.velocity = cForward * currentInputVector.y * verticalSprintSpeed * Time.fixedDeltaTime + cRight * currentInputVector.x * horizontalSprintSpeed * Time.fixedDeltaTime;
}
}
private void HandleInput()
{
isSprinting = Input.GetButton("Sprint");
Vector2 input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
currentInputVector = Vector2.SmoothDamp(currentInputVector, input, ref smoothInputVelocity, accelerationSpeed);
}
}
I think this thread may help --https://answers.unity.com/questions/9985/limiting-rigidbody-velocity.html.
Basically, there are two methods.
Add force in the opposite direction and increase with the extent to which the object exceeds the limit. This requires additional calculations and tests.
simply normalize the velocity value when it exceeds the limit.

How can i make the camera to lookat the next target and then rotate and move to the next target?

The first script is just making the camera to move over the terrain this script i'm not changing anything. The second script is PatrolData with that i feed the first script with data. The last script is the LookAt that should rotate the camera just a bit before moving to the next target(waypoint).
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 ((bool)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;
}
}
Then the data script:
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 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;
public Vector3 distanceFromTarget;
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:
iterator = Modulus(iterator, length * 2);
index = length - Mathf.Abs(length - iterator);
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;
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;
lingerDuration -= Time.deltaTime;
}
else
{
flyOverTerrain.target = patrol.target;
}
distanceFromTarget = transform.position - patrol.target.position;
}
private int Modulus(int baseNumber, int modulus)
{
return (modulus == 0) ? baseNumber : baseNumber - modulus * (int)Mathf.Floor(baseNumber / (float)modulus);
}
}
And the lookat script
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
_direction = (target.position - transform.position).normalized;
//create the rotation we need to be in to look at the target
_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);
}
}
All scripts are attached to the Main Camera. Until now it was working fine the camera moved between the targets. Now what i want to do is when the camera stop near each target just a bit before the camera start moving to the next target make a rotation to be facing to the target it's going to be moving to.
The problem is i don't know how to make it wait and how much and when to start the rotation in the LookAtCamera script.
Now what it does when running the game it's start rotating right away to the next target(in inspector i dragged for testing the second target).
My problem is how to work with the LookAtCamera script.
Found how to do it.
First in the LookAtCamera script that attached it to the Main Camera i also check that there is a target existing in the Update function:
if (target)
so the Update function:
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
_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);
}
Then in the script PatrolData:
The script PatrolData can be attached to any gameobject in this case i attached it to the Main Camera too.
In the top of FlyToVerTerrain i added:
public LookAtCamera lookAtCamera;
Then in the Update function:
lookAtCamera.target = patrol.target;
lookAtCamera.RotationSpeed = 3;
Then at this part:
if (targetOffset.sqrMagnitude <= sqrDistance)
{
flyOverTerrain.target = null;
lookAtCamera.target = null;
lingerDuration -= Time.deltaTime;
}
else
{
flyOverTerrain.target = patrol.target;
lookAtCamera.target = patrol.target;
}
In the end all the 3 scripts make that the camera will move to each waypoint(target), The camera will rotate and will face to the next waypoint before moving to the next waypoint.
Working perfect.

Why Isn't ray collisions working in unity

So I was working through this tutorial.
https://www.youtube.com/watch?v=OBtaLCmJexk
and I can't find the error in my code anywhere
The problem is just that after working on the vertical ray collisions I run the program and the block just falls through the obstacle.
here is the player code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Controller2D))]
public class Player : MonoBehaviour {
float gravity = -20;
Vector3 velocity;
Controller2D controller;
void Start() {
controller = GetComponent<Controller2D>();
}
void Update() {
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}
and here is the Controller2D code:
using UnityEngine;
[RequireComponent(typeof(BoxCollider2D))]
public class Controller2D : MonoBehaviour {
public LayerMask collisionMask;
const float skinWidth = .015f;
public int horizontalRayCount = 4;
public int verticalRayCount = 4;
float horizontalRaySpacing;
float verticalRaySpacing;
BoxCollider2D collider;
RaycastOrigins raycastOrigins;
void Start() {
collider = GetComponent<BoxCollider2D>();
CalculateRaySpacing();
}
public void Move(Vector3 velocity) {
UpdateRaycastOrigins();
VerticalCollisions(ref velocity);
transform.Translate(velocity);
}
void VerticalCollisions(ref Vector3 velocity) {
float directionY = Mathf.Sign(velocity.y);
float rayLength = Mathf.Abs(velocity.y) + skinWidth;
for (int i = 0; i < verticalRayCount; i++) {
Vector2 rayOrigin = (directionY == -1) ? raycastOrigins.bottomLeft : raycastOrigins.topLeft;
rayOrigin += Vector2.right * (verticalRaySpacing * i + velocity.x);
RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.up * directionY, rayLength, collisionMask);
Debug.DrawRay(raycastOrigins.bottomLeft + Vector2.right * verticalRaySpacing * i, Vector2.up * -2, Color.red);
if (hit) {
velocity.y = (hit.distance - skinWidth) * directionY;
rayLength = hit.distance;
}
}
}
void UpdateRaycastOrigins() {
Bounds bounds = collider.bounds;
bounds.Expand(skinWidth * -2);
raycastOrigins.bottomLeft = new Vector2(bounds.min.x, bounds.min.y);
raycastOrigins.bottomRight = new Vector2(bounds.max.x, bounds.min.y);
raycastOrigins.topLeft = new Vector2(bounds.min.x, bounds.max.y);
raycastOrigins.topRight = new Vector2(bounds.max.x, bounds.max.y);
}
void CalculateRaySpacing() {
Bounds bounds = collider.bounds;
bounds.Expand(skinWidth * -2);
horizontalRayCount = Mathf.Clamp(horizontalRayCount, 2, int.MaxValue);
verticalRayCount = Mathf.Clamp(verticalRayCount, 2, int.MaxValue);
horizontalRaySpacing = bounds.size.y / (horizontalRayCount - 1);
verticalRaySpacing = bounds.size.y / (verticalRayCount - 1);
}
struct RaycastOrigins {
public Vector2 topLeft, topRight;
public Vector2 bottomLeft, bottomRight;
}
}
Edit: The code is (as I understand from a half an hour tutorial.) just defining attributes to a quad(player) so that it can collide with another quad(obstacle). at the moment the code should only work vertically. so I am testing it by drawing the obstacle under the player and pressing play. the player should come to rest on the obstacle but instead, it sinks straight through it.
My screen after selecting the player block
and asking about debugging, I dont understand the language well enough to not break anything while trying to debug it.
I just got someone on discord to help and it turns out I didn't have the obstacle set with boxcollider2D
Many Thanks all who tried.

How can i make the enemy to move to next waypoint if there ius a very big waypoint in the middle?

If the waypoints are small size for example cubes at size 0.1 or 1 it's fine.
When i change the cubes size to 20-30 if there is a situation that there are two waypoints on the way but the enemy should get to the second waypoint he will stuck on the wall of the first waypoint will shake/stutter and will try to go to one of the sides and then in the end he will pass this waypoint and continue to the waypoint he should get the target.
It happen only when the waypoints(cubes) are very big and if a waypoint block the waypoint the enemy should get.
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityStandardAssets.Characters.ThirdPerson;
public class WayPoints : MonoBehaviour {
public GameObject[] waypoints;
public Transform target;
public float moveSpeed = 10f;
public float moveSpeed1 = 10f;
public float slowDownSpeed = 3f;
public float reverseSlowDownSpeed = 3f;
public float rotationSpeed = 1f;
private Transform myTransform;
private int targetsIndex = 0;
private Vector3 originalPosition;
private GameObject[] robots;
public Transform reverseTarget;
private int reverseTargetsIndex = 0;
private Vector3 reverseOriginalPosition;
public bool random = false;
void Awake()
{
myTransform = transform;
}
// Use this for initialization
void Start()
{
waypoints = GameObject.FindGameObjectsWithTag("ClonedObject");
robots = GameObject.FindGameObjectsWithTag("Robots");
AddColliderToWaypoints();
originalPosition = robots[0].transform.position;
reverseOriginalPosition = robots[1].transform.position;
}
// Update is called once per frame
void Update()
{
if (MyCommands.walkbetweenwaypoints == true)
{
WayPointsAI();
ReverseWayPointsAI();
}
DrawLinesInScene();
}
private void WayPointsAI()
{
if (targetsIndex == waypoints.Length)
targetsIndex = 0;
target = waypoints[targetsIndex].transform;
float distance = Vector3.Distance(robots[0].transform.position, target.transform.position);
robots[0].transform.rotation = Quaternion.Slerp(robots[0].transform.rotation, Quaternion.LookRotation(target.position - robots[0].transform.position), rotationSpeed * Time.deltaTime);
//move towards the player
if (distance < 30)
{
robots[0].transform.position += robots[0].transform.forward * slowDownSpeed * Time.deltaTime;
}
else
{
robots[0].transform.position += robots[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(robots[1].transform.position, reverseTarget.transform.position);
robots[1].transform.rotation = Quaternion.Slerp(robots[1].transform.rotation, Quaternion.LookRotation(reverseTarget.position - robots[1].transform.position), rotationSpeed * Time.deltaTime);
//move towards the player
if (distance < 30)
{
robots[1].transform.position += robots[1].transform.forward * reverseSlowDownSpeed * Time.deltaTime;
}
else
{
robots[1].transform.position += robots[1].transform.forward * moveSpeed1 * Time.deltaTime;
}
if (distance < reverseTarget.transform.localScale.magnitude)
{
reverseTargetsIndex--;
}
}
void RandomWayPointsAI()
{
if (random == true)
{
int index = 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, robots[0].transform.position, Color.red);
Debug.DrawLine(reverseOriginalPosition, robots[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, robots[0].transform.position, Color.green);
if (reverseTarget != null)
Debug.DrawLine(reverseTarget.transform.position, robots[1].transform.position, Color.green);
}
void AddColliderToWaypoints()
{
foreach (GameObject go in waypoints)
{
SphereCollider sc = go.AddComponent<SphereCollider>() as SphereCollider;
sc.isTrigger = true;
}
}
}
I tried to make
if (distance < reverseTarget.transform.localScale.magnitude)
I tried before it to make
if (distance < reverseTarget.tranform.localscale.x)
Or
if (distance < reverseTarget.tranform.localscale.x / 2)
Same with target and the first AI function.
But nothing is working. Maybe i should find the waypoints radius ?
Not sure how to solve it.
What OP seems to have wanted was a way to give the AI pathfinding so that when the AI wanted to go from (dynamic/code generated) point A to B and there was an obstacle between, the AI wouldn't get stuck in the obstacle.
Unity offers NavMesh and NavMesh Obstacle, a simple pathfinding tool Unity gives us to achieve a smart AI with little effort.

Categories