Unity3D Flying AI movement (Helicopter) - c#

I want make an helicopter ai for game,
but i can't figure out how can i do flying movement.
I need 2 types of movement(Flying around and Flying to)
Helicopter will spawn at corner of map and fly to some player - FlyingTo
after Heli will arrive to a player it will start Flying around
and shoot missile.
I tried use transform.Translate, transform.rotation, rigidbody.force and many other things to movement, but didn't find anything working.
Few of my tries:
Vector3 flyto = (nearest.transform.position + new Vector3(0, 100, 0));
Vector3 Kouzlo1 = new Vector3(base.transform.position.x, 0, base.transform.position.z);
Vector3 Kouzlo2 = new Vector3(nearest.transform.position.x, 0, nearest.transform.position.z);
/*Vector3 targetDir = flyto - transform.position;
float step = 10 * Time.deltaTime;
Vector3 newDir = Vector3.RotateTowards(transform.forward, targetDir, step, 0.0f);
transform.rotation = Quaternion.LookRotation(newDir);*/
if (Vector3.Distance(Kouzlo1, Kouzlo2) < 100)
{
var rotate = Quaternion.LookRotation(flyto - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, rotate,
Time.deltaTime * 10);
transform.Translate(Vector3.forward * 10 * Time.deltaTime);
/*transform.position = new Vector3(transform.position.x -
Vector3.Distance(Kouzlo1, Kouzlo2), nearest.transform.position.y + 100,
transform.position.z - Vector3.Distance(Kouzlo1, Kouzlo2));
Vector3 vvv = transform.rotation * new Vector3(0f, 1f, 0f);
transform.RotateAround(flyto, vvv, 180 * Time.deltaTime);*/
//transform.RotateAround(flyto, Vector3.forward, 10 * Time.deltaTime);
}else {
//transform.rotation = Quaternion.Slerp(transform.rotation,
Quaternion.LookRotation(flyto -transform.position), 10 * Time.deltaTime);
//transform.position += transform.forward * 10 * Time.deltaTime;
transform.LookAt(nearest.transform.position);
rigidbody.AddForce(Vector3.forward * 10);
}

You need to understand the method Lerp / Slerp first.
Lerp(a, b, t);
When t=0 it returns a, t=1 it returns b, otherwise it returns a value between a and b.
So you may use
Quaternion.Slerp(a, b, t += Time.deltaTime * 10);
And there is another similar method RotateTowards (or MoveTowards in Vector3 / Mathf class) can do same work
Quaternion.RotateTowards(a, b, Time.deltaTime);

Related

Rotate player on z axis while walking

i'm currently in progress of a new game where my character has to move. While my character walks forward and i'm rotating it on the z axis, it just rotates instead of walking down the new z axis.
void Update()
{
{
if (Input.GetKeyDown(KeyCode.W))
{
anim.SetInteger("Condition", 1);
moveDir = new Vector3(0, 0, 1);
moveDir *= speed;
moveDir = transform.TransformDirection(moveDir);
}
if (Input.GetKeyUp(KeyCode.W))
{
anim.SetInteger("Condition", 0);
moveDir = new Vector3(0, 0, 0);
}
moveDir.y -= gravity * Time.deltaTime;
controller.Move(moveDir * Time.deltaTime);
}
rot += Input.GetAxisRaw("Horizontal") * rotSpeed * Time.deltaTime;
transform.eulerAngles = new Vector3(0, rot, 0);
}
}
I want to be able to walk forward while changing the z axis instead of walking then stop and then walk again.
You can't do that using a CharacterController because your call to controller.move() overwrites the rotation ... you need to write a custom move function.

MathF.Clamp issue

I'm following a tutorial in C# and Unity and i have deviated a little off the code, I was hoping someone could help me understand how to add a MathF.Clamp to my code.
var delta = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")).normalized * Time.deltaTime * moveSpeed;
transform.position = new Vector3(
transform.position.x + delta.x,
transform.position.y + delta.y,
transform.position.z);
All advice is welcome. Thank you for your time.
Since you're using an orthographic camera, you can still use Mathf.Clamp and ViewportToWorldPoint. You'll just need to use it for each component. You can get the min and max for the x and y together by using ViewportToWorldPoint(new Vector3(0,0,0)); and ViewportToWorldPoint(new Vector3(1,1,0));.
Altogether, this might look like this:
private Camera mainCam;
Start()
{
// Camera.main calls FindGameObjectsWithTag internally, which is a costly operation.
// It's best to cache the results of Camera.main when possible to save on computation.
mainCam = Camera.main;
}
Update()
{
var delta = new Vector2(Input.GetAxisRaw("Horizontal"),
Input.GetAxisRaw("Vertical")).normalized * Time.deltaTime * moveSpeed;
Vector3 minPos = mainCam.ViewportToWorldPoint(new Vector3(0,0,0));
Vector3 maxPos = mainCam.ViewportToWorldPoint(new Vector3(1,1,0));
transform.position = new Vector3(
Mathf.Clamp(transform.position.x + delta.x, minPos.x, maxPos.x),
Mathf.Clamp(transform.position.y + delta.y, minPos.y, maxPos.y),
transform.position.z);
}
This will keep your camera in bounds using Mathf.Clamp. You have to define the min and max values where the camera is allowed to move:
var delta = new Vector2(Input.GetAxisRaw("Horizontal"),
Input.GetAxisRaw("Vertical")).normalized * Time.deltaTime * moveSpeed;
transform.position = new Vector3(
Mathf.Clamp(transform.position.x + delta.x, minX, maxX),
Mathf.Clamp(transform.position.y + delta.y, minY, maxX),
transform.position.z);
You can try something like this:
var delta = new Vector2(Input.GetAxisRaw("Horizontal"),
Input.GetAxisRaw("Vertical")).normalized * Time.deltaTime * moveSpeed;
transform.position = new Vector3(
Mathf.Clamp(transform.position.x + delta.x, minX, maxX),
Mathf.Clamp(transform.position.y + delta.y, minY, maxX),
transform.position.z);

I want my character to move only in the direction that it is looking

I have a 3D game, where my camera is looking at all my terrain, and I have a character that moves with an Xbox controller. I want my character to only move in the direction that it is looking, not to the sides. I have the next code that makes my character move.
void Update()
{
MoveInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical"));
moveVelocity = MoveInput * MoveSpeed;
Vector3 PlayerDirection = Vector3.right * -Input.GetAxisRaw("RHorizontal") + Vector3.forward * -Input.GetAxisRaw("RVertical");
if (PlayerDirection.sqrMagnitude > 0.0f)
{
transform.rotation = Quaternion.LookRotation(PlayerDirection, Vector3.up);
}
The character moves with the left side of the controller, and with the right side, I can move the direction that is facing.
Currently, you're using the inputs as x and z components of a world space direction. It doesn't take into account the rotation of the character at all.
Instead, you should multiply the inputs and the corresponding local direction in world space, and then combine them. In your case, this might look like this:
MoveInput = (
transform.right * Input.GetAxisRaw("Horizontal")
+ transform.forward * Input.GetAxisRaw("Vertical")
).normalized;
moveVelocity = MoveInput * MoveSpeed;
Vector3 PlayerDirection = Vector3.right * -Input.GetAxisRaw("RHorizontal")
+ Vector3.forward * -Input.GetAxisRaw("RVertical");
if (PlayerDirection.sqrMagnitude > 0.0f)
{
transform.rotation = Quaternion.LookRotation(PlayerDirection, Vector3.up);
}
The normalized is so you don't move faster diagonally.
I found a solution, here is the code:
MoveInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical"));
moveVelocity = MoveInput * MoveSpeed;
Vector3 PlayerDirection = Vector3.right * Input.GetAxisRaw("Horizontal") + Vector3.forward * Input.GetAxisRaw("Vertical");
if (PlayerDirection.sqrMagnitude > 0.0f)
{
transform.rotation = Quaternion.LookRotation(PlayerDirection, Vector3.up);
}

Unity3D - Third Person Player movement in diagonal direction is slower than vertical and horizontal movement?

I'm trying to create a character controller that allows the movement speed to be affected by how far the player is pressing the left stick. When I can get that much to work, the other issue I encounter is the players speed decreasing while moving diagonally.
Most of the information I've found online deal with the opposite issue where diagonal movement is faster (movement vector goes above 1). The solution there would be to clamp the magnitude so pressing the stick into a corner doesn't go above 1. I've tried clamping to see if that would work, however, I don't believe that's the solution to my problem.
The code here allows the player to move in relation to the camera and the speed is influenced by input vector.
Vector3 input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
Vector3 inputDir = input.normalized;
void Move(Vector3 inputDir, Vector3 input)
{
running = Input.GetKey(KeyCode.Joystick1Button1); // B button on xbox one controller
// Rotation stuff
if (inputDir != Vector3.zero) {
float targetRotation = Mathf.Atan2(inputDir.x, inputDir.z) * Mathf.Rad2Deg + cameraTransform.eulerAngles.y;
transform.eulerAngles = Vector3.up * Mathf.SmoothDampAngle(transform.eulerAngles.y, targetRotation, ref turnSmoothVelocity, GetModifiedSmoothTime(speedSmoothTime));
}
// Pretty sure this is where things are breaking
float targetSpeed = ((running) ? runSpeed : walkSpeed) * inputDir.magnitude;
currentSpeed = Mathf.SmoothDamp(currentSpeed, targetSpeed, ref speedSmoothVelocity, GetModifiedSmoothTime(speedSmoothTime));
currentSpeed *= input.magnitude;
vel = transform.forward * currentSpeed + Vector3.up * velocityY;
currentSpeed = new Vector3(_controller.velocity.x, 0, _controller.velocity.z).magnitude;
}
void ExecuteMovement()
{
_controller.Move(vel * Time.deltaTime);
}

Change movement according to camera direction

Good day. I'm working on a fps game, and I have a problem with camera, or with movement to be pricese... as it doesn't take camera position into accound when performs movement...
I tried to fix it in several different ways, but I guess I just don't understand the math needed :(
Anyway, here's the code:
static public void UpdateCharacterPositionAndCamera(float time)
{
//mouse look update
float rotationSpeed = 3f;
if (Input.mouseState != Input.mouseStatePrevious)
{
float xDifference = Input.mouseState.X - Display.gd.Viewport.Width / 2;
float yDifference = Input.mouseState.Y - Display.gd.Viewport.Height / 2;
yRotation -= rotationSpeed * xDifference * time;
xRotation -= rotationSpeed * yDifference * time;
Mouse.SetPosition(Display.gd.Viewport.Width / 2, Display.gd.Viewport.Height / 2);
}
//camera
Vector3 cameraPosition = playerPos;
Vector3 cameraReference = new Vector3(0f, 0f, -1f);
Matrix rotationMatrix = Matrix.CreateRotationY(MathHelper.ToRadians(yRotation)) * Matrix.CreateRotationX(MathHelper.ToRadians(xRotation));
Vector3 transformedReference = Vector3.Transform(cameraReference, rotationMatrix);
Vector3 cameraLookat = cameraPosition + transformedReference;
viewMatrix = Matrix.CreateLookAt(cameraPosition, cameraLookat, new Vector3(0.0f, 1.0f, 0.0f));
projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, Display.gd.Viewport.AspectRatio, 0.1f, 2500.0f);
//movement
float moveSpeed = 5.0f;
Vector3 moveVector = new Vector3(0, 0, 0);
if (Input.keyState.IsKeyDown(Keys.Up) || Input.keyState.IsKeyDown(Keys.W))
moveVector += new Vector3(0, 0, -1);
if (Input.keyState.IsKeyDown(Keys.Down) || Input.keyState.IsKeyDown(Keys.S))
moveVector += new Vector3(0, 0, 1);
if (Input.keyState.IsKeyDown(Keys.Right) || Input.keyState.IsKeyDown(Keys.D))
moveVector += new Vector3(1, 0, 0);
if (Input.keyState.IsKeyDown(Keys.Left) || Input.keyState.IsKeyDown(Keys.A))
moveVector += new Vector3(-1, 0, 0);
if (Input.keyState.IsKeyDown(Keys.Q))
moveVector += new Vector3(0, 1, 0);
if (Input.keyState.IsKeyDown(Keys.Z))
moveVector += new Vector3(0, -1, 0);
playerPos += moveVector * moveSpeed;
}
Can you tell me how to change the move vector so it takes camera direction into account...?
Multiply the move vector by the camera rotation matrix, or its inverse (I think it's the inverse). It's the same as the view matrix, but without the translation. If you want to fix the camera onto a plane, you need to zero out the respective component afterwards and perhaps normalize the new vector.
I'm not familiar with the XNA API, so I cannot tell you exactly which methods to use. You might be able to extract the rotation matrix from the view matrix, or you might need to look at the difference (lookAt-positios) from the origin.
aere's how I usually do it:
//movement
Matrix camWorld = Matrix.Invert(view);
Vector3 moveVector = Vector3.Zero;
...
if(...keys.Up... or ...keys.W...)
moveVector += camWorld.Forward;
if(... keys.right or ... keys.D...)
moveVector += camWorld.Right;
...
moveVector.Normalize();
PlayerPos += moveVector * moveSpeed;

Categories

Resources