- Home /
[C#] AI Behaviour in spherical way like RESOGUN based on Rigidbodies.
Hey all, I've looked all over the internet for ways to implement this kind of behaviour for enemy AI: https://www.youtube.com/watch?v=mscD8heTjZw
but havent found a satisfying answer for it. The way I want my enemies to move is like in the link ^. I figured there are different ways to actually achieve this, but my head is stuck on this matter for over a week now. I wonder how the devs actually made this.
Is the world "Curved" towards a sphere so the enemies just move "forward" without even touching rotations?
Do they make use of boundaries the enemies stay in?
Do they use spherical gravity for the centre of the sphere?
I just cant figure out how they made this and how I should do this.
I have found some helpful threads however on spherical movement, but to actually implement difficult AI behaviour for my enemies, this does not seem to be the way to go, since I would like to use some kind of physics for steering and translating my enemies. Trying to prevent usage of: Transform.position = ...........
Anyways, here is my question: How to implement AI - Rigidbody behaviour like in Resogun?
Answer by BL1TZ · Apr 28, 2017 at 05:43 AM
So, I've managed to write the behaviour that I want, I'll post the solution for anyone who is stuck on spherical movement too, but does not need rigidbodies involved.
using System.Collections;
using UnityEngine;
public class SphericMovement : MonoBehaviour
{
public GameObject sphere;
private Vector3 origin;
[Range(0, 100)]
public float _speed = 1f;
public bool clockWise = true;
private float speed = 0f;
private float angleOnSphere = 0f;
private float radius = 0f;
private float direction;
public float AngleOnSphere { get { return angleOnSphere; } set { angleOnSphere = value; } }
public float Speed
{
get { return speed; }
set { speed = value; }
}
void Start()
{
// Used to set the standard height of the enemy.
origin = new Vector3(0, transform.position.y, 0);
// Radius of a sphere is equal to the scale in any direction / 2 if it shares the same dimensions.
radius = sphere.transform.localScale.x / 2;
}
void Update()
{
UpdateDirection();
UpdatePosition();
}
void UpdateDirection()
{
// Check if the movement is clockWise or counter clockwise.
direction = GetDirectionFactor(clockWise);
// Update the angle rotation at which the cube rotates depending on direction.
angleOnSphere += speed * direction * Time.deltaTime;
}
void UpdatePosition()
{
// Calculate the new Rotation based on starting euler.y value multiplying it by the radius of the sphere it moves on.
Vector3 newPos = Quaternion.Euler(1f, angleOnSphere, 1f) * new Vector3(0, 0, radius);
// Takes the begin position and adds a certain rotation to it based on the position of the enemy on the sphere.
transform.position = origin + newPos;
// Turns the forward (blue) axis towards the movement vector of the cube.
transform.forward = Quaternion.Euler(1f, (angleOnSphere + (90 * direction)), 1f) * new Vector3(0f, 0f, radius);
}
private float GetDirectionFactor(bool clockwise)
{
if (clockWise)
return 1f;
else if (!clockWise)
return -1f;
return 0f;
}
}
Now the only problem I'm having is that I want this behaviour with Rigidbodies. So instead of setting the transform.position directly, I would want to change the velocity vector and just give the enemy a Rb.AddForce in the start function. The real problem starts now: Since I want to have the forward of the enemy to always follow the direction it is translating on the sphere, it is hard to know how fast I need the enemy to rotate as I want this to be scaled with the force I am applying to it.
To clarify: I am giving the enemy's rigidbody a force, but according to that it needs to rotate on the sphere with a different speed so it will stay on the sphere's surface. Can anybody help me with this?