The base is a red cube.
The spaceship is moving already when the game start.
When I click/press the L button the spaceship rotates to face the base and starts moving to it but then when it's getting close to the base it's behaving unexpectedly and the spaceship starts rolling around the base nonstop.
What I want is to make the landing automatic like this youtube video of blender.
I don't want the graphics but the way it's landing.
Blender landing spaceship
And this is a short video clip showing my spaceship when it's start landing:
Landing test
This is the script i'm using for controlling the spaceship and the landing part should be automatic.
The script is attached to the spaceship.
using UnityEngine;
using System.Collections;
public class ControlShip : MonoBehaviour {
public int rotationSpeed = 75;
public int movementspeed = 10;
public int thrust = 10;
public float RotationSpeed = 5;
private bool isPKeyDown = false;
private float acceleration = .0f;
private Vector3 previousPosition = Vector3.zero;
private Rigidbody _rigidbody;
private bool landing = false;
private Vector3 originPosition;
private Vector3 lastPosition;
private const float minDistance = 0.2f;
private Transform baseTarget;
// Use this for initialization
void Start () {
baseTarget = GameObject.Find("Base").transform;
originPosition = transform.position;
_rigidbody = GetComponent<Rigidbody>();
Debug.Log("Acc Speed: " + thrust);
}
// Update is called once per frame
void Update()
{
if (landing == false)
{
var v3 = new Vector3(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"), 0.0f);
transform.Rotate(v3 * rotationSpeed * Time.deltaTime);
transform.position += transform.forward * Time.deltaTime * movementspeed;
if (Input.GetKey(KeyCode.Z))
transform.Rotate(Vector3.forward * rotationSpeed * Time.deltaTime);
if (Input.GetKey(KeyCode.R))
transform.Rotate(Vector3.right * rotationSpeed * Time.deltaTime);
if (Input.GetKey(KeyCode.P))
{
isPKeyDown = Input.GetKey(KeyCode.P);
float distance = Vector3.Distance(previousPosition, transform.position);
acceleration = distance / Mathf.Pow(Time.deltaTime, 2);
previousPosition = transform.position;
_rigidbody.AddRelativeForce(0f, 0f, thrust, ForceMode.Acceleration);
}
}
else
{
transform.position += transform.forward * Time.deltaTime * movementspeed;
var targetRotation = Quaternion.LookRotation(baseTarget.position - transform.position);
var str = Mathf.Min(.5f * Time.deltaTime, 1);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, str);
}
if (landed == true)
TakeOff();
if (Input.GetKey(KeyCode.L))
{
landing = true;
lastPosition = transform.position;
}
}
void OnTriggerEnter(Collider other)
{
if (landing == true && other.gameObject.name == "Base")
{
StartCoroutine(Landed());
}
}
bool landed = false;
IEnumerator Landed()
{
yield return new WaitForSeconds(5);
Debug.Log("Landed");
landed = true;
}
private void TakeOff()
{
if (transform.position != originPosition)
{
_rigidbody.AddForce(transform.up * 10);
}
if ((transform.position - originPosition).sqrMagnitude <= (1f * 1f))
{
landed = false;
_rigidbody.useGravity = false;
}
}
void OnGUI()
{
if (isPKeyDown)
{
GUI.Label(new Rect(100, 100, 200, 200), "Acc Speed: " + acceleration);
}
}
}
This is the part of the landing, should be the part of the landing:
transform.position += transform.forward * Time.deltaTime * movementspeed;
var targetRotation = Quaternion.LookRotation(baseTarget.position - transform.position);
var str = Mathf.Min(.5f * Time.deltaTime, 1);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, str);
The spaceship have two components: Rigidbody, Use Gravity set to true. And a Box Collider.
The Base have a box collider component.
You appear to have a box collider on your vehicle and it looks as though it is colliding with the terrain when your code tries to bring it in for a landing. Try switching the collider to be a trigger(tick option on collider component).
Then try it again, as this will not cause physical collisions. If it works or fails for a totally different reason you know this is the cause or a contributing factor.
EDIT: It is worth also noting that when trying to achieve this kind of effect it can be much easier to trigger an animation than try to achieve it in physics based code. Unity offers some great animation controllers and you can call an animation when you need to land since you are taking control away from the player anyway.
While doing this you could turn off the collider so you don't get any strange collision then turn it on when the ship needs to take off, provided you need that of course.
Hope it helps.
Related
I just can’t figure out how to make random points for patrolling, I went through 100 manuals, but I can’t do it.
No need to write about NavMeshAgent. Not used.
using System.Collections;
using UnityEngine;
public sealed class Manikin : MonoBehaviour {
private Vector3 StartManikin = Vector3.zero,
NewPosition = Vector3.zero;
private readonly float Speed = 2.0f;
void Start() {
StartManikin = transform.position;
}
void Update() {
if (Vector3.zero == NewPosition) {
NewPosition = StartManikin + Random.onUnitSphere * 2;
}
if (Vector3.Distance(transform.position, NewPosition) < 0.1f) {
StartManikin = transform.position;
NewPosition = Vector3.zero;
} else {
transform.LookAt(new Vector3(NewPosition.x, StartManikin.y, NewPosition.z));
transform.position = Vector3.MoveTowards(transform.position, NewPosition, Speed * Time.deltaTime);
}
}
}
The problem is that there may be obstacles in the form of a fence, a tree, houses, cars, etc.
I need that when the enemy appears, random points are generated in his radius so that he does not leave further.
Help me out, I can’t figure out what needs to be done to make everything work ...
It turns out that I just did not see that the Pivot of the model is not clear where, it flies in another dimension, the problem is solved, it is necessary to reset all transformations and the world point of the model's coordinates.
I didn’t see it right away, all the options turned out to be working ...
And also, it was necessary to fix the problem with the take-off along the y-axis, so that this does not happen, you need to look at the bottom point of the object from which we will spawn the coordinate for it.
if (Vector3.zero == NewPosition) {
NewPosition = StartManikin + (Random.onUnitSphere * 5);
NewPosition.y = transform.GetComponent<CapsuleCollider>().bounds.min.y;
}
if (Vector3.Distance(transform.position, NewPosition) < 0.1f) {
StartManikin = transform.position;
NewPosition = Vector3.zero;
} else {
transform.LookAt(new Vector3(NewPosition.x, transform.position.y, NewPosition.z));
transform.position = Vector3.MoveTowards(transform.position, NewPosition, Speed * Time.deltaTime);
}
whenever I turn my bike it feels like it's sliding. Here's the script
[SerializeField] float turn;
[SerializeField] float maxSpeed;
[SerializeField] GameObject bikeParts;
[SerializeField] float tilt = 20f;
Rigidbody rb;
float lastY;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
float straightMov = Input.GetAxis("Vertical");
float horizontalMov = Input.GetAxis("Horizontal");
ControlStraightMov(straightMov);
ControlWeightTurning(horizontalMov);
lastY = transform.position.y;
}
private void ControlWeightTurning(float horizontalMov)
{
Vector3 bikePartsRot = bikeParts.transform.eulerAngles;
bikePartsRot.x = tilt * horizontalMov;
bikeParts.transform.eulerAngles = bikePartsRot;
transform.Rotate(0f, (turn * Time.deltaTime) * horizontalMov, 0f);
}
private void ControlStraightMov(float straightMov)
{
if (straightMov > 0)
{
rb.AddRelativeForce((accel * Time.deltaTime) * -straightMov, 0f, 0f);
}
else if (straightMov < 0)
{
rb.AddRelativeForce(((accel / 1.3f * Time.deltaTime) * -straightMov), 0f, 0f);
}
}
Whenever the bike picks up speed, it becomes very difficult to turn the bike because the force that was added keeps moving the bike in a different direction than the direction the bike's facing, how do I apply that force it was facing before on the direction it is facing now so that it doesn't feel like sliding?
I have tried fixing this problem but i just can't because i am pretty new to unity.
how do I apply that force it was facing before on the direction it is facing now
Not sure if this would feel right but you could probably do it like e.g.
private void Update ()
{
...
rb.velocity = transform.forward * rb.velocity.magnitude;
}
Which will keep the current speed and just redirect it into the new forward direction.
In general note: Whenever there is a Rigidbody involved you don't want to set any manipulation through the Transform component but only via the Rigidbody.
So you should not do
bikeParts.transform.eulerAngles = bikePartsRot;
transform.Rotate(0f, (turn * Time.deltaTime) * horizontalMov, 0f);
but both times rather calculate the target rotation and go through e.g. rb.MoveRotation in FixedUpdate.
Which might look somewhat like
float horizontalMove;
void Update()
{
var straightMove = Input.GetAxis("Vertical");
// Get and store the input in Update
horizontalMove = Input.GetAxis("Horizontal");
ControlStraightMov(straightMove);
lastY = transform.position.y;
}
private void FixedUpdate ()
{
// Handle it in FixedUpdate
ControlWeightTurning(horizontalMove);
}
private void ControlWeightTurning(float horizontalMove)
{
var bikePartsRot = bikeParts.transform.eulerAngles;
bikePartsRot.x = tilt * horizontalMove;
// Calculate the new final rotation
var newRotation = Quaternion.Euler(bikePartsRot) * Quaternion.Euler(Vector3.up * (turn * Time.deltaTime) * horizontalMove));
// Apply it only via the Rigidbody
rb.MoveRotation(newRotation);
}
I have began developing an fps script and followed a tutorial to help with the script. Everything works great now but the only issue is any objects in the view seem to stutter whenever the player is moving and rotating at the same time.
The script for the player's movement and camera rotation is below.
Can anybody point me in the right direction?
Thank you.
{
public Transform cam;
public Rigidbody rb;
public float camRotationSpeed = 5f;
public float camMinimumY = -60f;
public float camMaximumY = 75f;
public float rotationSmoothSpeed = 10f;
public float walkSpeed = 9f;
public float runSpeed = 14f;
public float maxSpeed = 20f;
public float jumpPower = 30f;
public float extraGravity = 45;
float bodyRotationX;
float camRotationY;
Vector3 directionIntentX;
Vector3 directionIntentY;
float speed;
public bool grounded;
void Update()
{
LookRotation();
Movement();
ExtraGravity();
GroundCheck();
if(grounded && Input.GetButtonDown("Jump"))
{
Jump();
}
}
void LookRotation()
{
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
bodyRotationX += Input.GetAxis("Mouse X") * camRotationSpeed;
camRotationY += Input.GetAxis("Mouse Y") * camRotationSpeed;
camRotationY = Mathf.Clamp(camRotationY, camMinimumY, camMaximumY);
Quaternion camTargetRotation = Quaternion.Euler(-camRotationY, 0, 0);
Quaternion bodyTargetRotation = Quaternion.Euler(0, bodyRotationX, 0);
transform.rotation = Quaternion.Lerp(transform.rotation, bodyTargetRotation, Time.deltaTime * rotationSmoothSpeed);
cam.localRotation = Quaternion.Lerp(cam.localRotation, camTargetRotation, Time.deltaTime * rotationSmoothSpeed);
}
void Movement()
{
directionIntentX = cam.right;
directionIntentX.y = 0;
directionIntentX.Normalize();
directionIntentY = cam.forward;
directionIntentY.y = 0;
directionIntentY.Normalize();
rb.velocity = directionIntentY * Input.GetAxis("Vertical") * speed + directionIntentX * Input.GetAxis("Horizontal") * speed + Vector3.up * rb.velocity.y;
rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxSpeed);
if (Input.GetKey(KeyCode.LeftShift))
{
speed = runSpeed;
}
if (!Input.GetKey(KeyCode.LeftShift))
{
speed = walkSpeed;
}
}
void ExtraGravity()
{
rb.AddForce(Vector3.down * extraGravity);
}
void GroundCheck()
{
RaycastHit groundHit;
grounded = Physics.Raycast(transform.position, -transform.up, out groundHit, 1.25f);
}
void Jump()
{
rb.AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
}
}
This probably happens because the frame needs to update the camera rotation and the player position at the same time. i would suggest doing the rotation of the camera in fixed update. because this will run at the end of each frame.
like this:
void FixedUpdate()
{
LookRotation();
}
another thing i would suggest is to move the player while the groundcheck is being ran, because if you do it seperately i can see a bug coming up when the player moves faster then the code can run or something. so a tip would be or to run it inside the movement method, or call the method while you are calling the movement method.
this:
void Movement()
{
directionIntentX = cam.right;
directionIntentX.y = 0;
directionIntentX.Normalize();
directionIntentY = cam.forward;
directionIntentY.y = 0;
directionIntentY.Normalize();
rb.velocity = directionIntentY * Input.GetAxis("Vertical") * speed + directionIntentX * Input.GetAxis("Horizontal") * speed + Vector3.up * rb.velocity.y;
rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxSpeed);
if (Input.GetKey(KeyCode.LeftShift))
{
speed = runSpeed;
}
if (!Input.GetKey(KeyCode.LeftShift))
{
speed = walkSpeed;
}
GroundCheck();
}
or litteraly copy and paste the code within your movement method.
I've been trying to figure this out for a few days now, and I'm very sure it has something to do with my code. What I want the enemy monster to do is to stop moving forward when the player right next to it and run the attack animation. What it actually does is run the attack animation while orbiting around the player like a planet, and you can't really outrun it.
I'm using Unity3d as the engine and my code is written in C#. It's very simple so I'm worried I'm missing something important.
public class enemyAITest : MonoBehaviour
{
public Transform player; // target
public float playerDistance; // determines how far from target before action takes place
public float rotationDamping; // determines how quickly rotation occurs
public float chaseSpeed; // determines how quickly to pursue target
public float wanderSpeed; // determines how quickly to move around map
public float maxDist;
static Animator anim;
Vector3 wayPoint;
void Awake()
{
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update ()
{
transform.position += transform.TransformDirection(Vector3.forward) * wanderSpeed * Time.deltaTime;
playerDistance = Vector3.Distance(player.position, transform.position);
while ((transform.position - wayPoint).magnitude < 3)
Wander();
if (playerDistance < 20f)
{
LookAtPlayer();
wanderSpeed = 0;
anim.SetBool("isIdle", true);
}
if (playerDistance < 10f)
{
Chase();
anim.SetBool("isIdle", false);
anim.SetBool("isWalking", false);
anim.SetBool("isRunning", true);
}
if(playerDistance < 1f)
{
wanderSpeed = 0;
anim.SetBool("isRunning", false);
anim.SetBool("isAttacking", true);
}
else anim.SetBool("isWalking", true);
}
void LookAtPlayer()
{
Quaternion rotation = Quaternion.LookRotation(player.position - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * rotationDamping);
wanderSpeed = 0;
}
void Chase()
{
Vector3 direction = player.position - transform.position;
direction.y = 0;
transform.Translate(Vector3.forward * chaseSpeed * Time.deltaTime);
}
void Wander()
{
Vector3 MonsterPosition = new Vector3(Random.Range(transform.position.x - maxDist, transform.position.x + maxDist), 1, Random.Range(transform.position.z - maxDist, transform.position.z + maxDist));
wayPoint.y = 1;
transform.LookAt(wayPoint);
//Debug.Log(wayPoint + " and " + (transform.position - wayPoint).magnitude);
}
}
Any advice will help (Please forgive the strange formatting, I was having trouble with keeping the entire Wander method and the on Awake line in the code block).
This is the script i'm using for testing the movements. The cube is moving forward make a rotation of 180 degrees and stop. The spaceship instead moving forward it's just moving up then in the it rotate and stop.
Why the spaceship is not moving like the cube forward ? I guess it's something with the spaceship physics but not sure if it is the problem and what and how to solve it.
This is a shot video clip i recordered showing the spaceship in hierarchy and it's inspector same for the cube.
Both attached with the same script at below i also show in the video what happening when running the game:
video clip
The problem is that the ship moving up and not forward when doing:
transform.position += transform.forward * Time.deltaTime * moveSpeed;
But the cube does move forward.
using UnityEngine;
using System.Collections;
public class MoveObject : MonoBehaviour {
public float moveSpeed = 1.0f;
public float smooth = 1f;
private float distanceTravelled;
private Vector3 startPositon;
private Vector3 targetAngles;
private bool isRotate = false;
// Use this for initialization
void Start () {
startPositon = new Vector3 (transform.position.x, transform.position.y, transform.position.z);
}
// Update is called once per frame
void Update () {
if (isRotate == false)
transform.position += transform.forward * Time.deltaTime * moveSpeed;
distanceTravelled += Vector3.Distance (transform.transform.position, startPositon);
if (distanceTravelled >= 100 && isRotate == false) {
targetAngles = transform.eulerAngles + 180f * Vector3.up;
StartCoroutine (TurnObject (transform, transform.eulerAngles, targetAngles, smooth));
isRotate = true;
}
}
IEnumerator TurnObject(Transform ship, Vector3 startAngle, Vector3 endAngle, float smooth)
{
float lerpSpeed = 0;
while(lerpSpeed < 1)
{
ship.eulerAngles = Vector3.Lerp(startAngle, endAngle, lerpSpeed);
lerpSpeed += Time.deltaTime * smooth;
yield return null;
}
}
}