I have this code and I can't figure out how to make the camera stop following my player when he jumps, in unity3d
using UnityEngine;
using System.Collections;
public class Camera2DFollow2 : MonoBehaviour {
public Transform target;
public float damping = 1;
public float lookAheadFactor = 3;
public float lookAheadReturnSpeed = 0.5f;
public float lookAheadMoveThreshold = 0.1f;
float offsetZ;
Vector3 lastTargetPosition;
Vector3 currentVelocity;
Vector3 lookAheadPos;
// Use this for initialization
void Start () {
lastTargetPosition = target.position;
offsetZ = (transform.position - target.position).z;
transform.parent = null;
}
// Update is called once per frame
void Update () {
// only update lookahead pos if accelerating or changed direction
float xMoveDelta = (target.position - lastTargetPosition).x;
bool updateLookAheadTarget = Mathf.Abs(xMoveDelta) > lookAheadMoveThreshold;
if (updateLookAheadTarget) {
lookAheadPos = lookAheadFactor * Vector3.right * Mathf.Sign(xMoveDelta);
} else {
lookAheadPos = Vector3.MoveTowards(lookAheadPos, Vector3.zero, Time.deltaTime * lookAheadReturnSpeed);
}
Vector3 aheadTargetPos = target.position + lookAheadPos + Vector3.forward * offsetZ;
Vector3 newPos = Vector3.SmoothDamp(transform.position, aheadTargetPos, ref currentVelocity, damping);
transform.position = newPos;
lastTargetPosition = target.position;
}
}
Try
Vector3 aheadTargetPos = target.position + lookAheadPos + Vector3.forward * offsetZ;
Vector3 newPos = Vector3.SmoothDamp(transform.position, aheadTargetPos, ref currentVelocity, damping);
newPos.y = transform.position.y;
transform.position = newPos;
or
Vector3 aheadTargetPos = target.position + lookAheadPos + Vector3.forward * offsetZ;
aheadTargetPos.y = transform.position.y;
Vector3 newPos = Vector3.SmoothDamp(transform.position, aheadTargetPos, ref currentVelocity, damping);
transform.position = newPos;
You can set a minimum threshold value for the Y value of character. When characters jump you can save that transform point y and look for the distance between that point and character position.y If the character exceeds that threshold, than your camera can follow the character. Also, you can consider using Cinemachine. It is very powerful. (https://unity.com/unity/features/editor/art-and-design/cinemachine)
Related
Why does my camera when moving up or down (camera has a top view) move to the y coordinate?
Here is the code:
using UnityEngine;
public class ScrollWheelMove : MonoBehaviour
{
private bool DragMoveActive;
private Vector2 LastMousePos;
private void Update()
{
Vector3 inputDir = new Vector3(0, 0, 0);
float DragPanSpeed = 3f;
if (Input.GetMouseButtonDown(2))
{
DragMoveActive = true;
LastMousePos = Input.mousePosition;
}
if (Input.GetMouseButtonUp(2))
{
DragMoveActive = false;
}
if (DragMoveActive)
{
Vector2 mouseMovementDelta = (Vector2)Input.mousePosition - LastMousePos;
inputDir.x = mouseMovementDelta.x * DragPanSpeed;
inputDir.z = mouseMovementDelta.y * 6f;
LastMousePos = Input.mousePosition;
}
float moveSpeed = 3f;
Vector3 moveDir = -transform.right * inputDir.x + -transform.forward * inputDir.z;
transform.position += moveDir * moveSpeed * Time.deltaTime;
}
}
I want my camera to move only along the coordinates x and z.
I tried to change the code with coordinates, speed. I also tried to constantly set the coordinates y = 40
I am trying to implement the seek algorithm of steering behaviors for cars. The way I have defined a path for the cars is by using spheres to signify waypoints.
I want the car to move along this waypoint using the seek algorithm. I am trying to do it in the following way. However, the car will only go to the first waypoint and get stuck there.
More specifically, my problem is that my implementation won't update wayIndex and this causes the target to never go to the next point in the waypoints array.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Follower : MonoBehaviour
{
public GameObject vehicle;
public float[] speeds = {15.0f,25.0f,35.0f};
public int pathChoice;
[SerializeField]
public Transform[] waypoints;
public Transform[] waypoints2;
[SerializeField]
public float speed;
private int wayIndex = 0;
private Vector3 target;
private Vector3 steering;
private void Start(){
int speedIndex = UnityEngine.Random.Range(0, 3);
int pathIndex = UnityEngine.Random.Range(0, 2);
speed = speeds[speedIndex];
pathChoice = pathIndex;
if (pathIndex == 0){
steering = Vector3.zero;
target = waypoints[wayIndex].position;
transform.position = waypoints[wayIndex].transform.position;
}else if (pathIndex == 1){
steering = Vector3.zero;
target = waypoints2[wayIndex].position;
transform.position = waypoints2[wayIndex].transform.position;
}
}
private void Update(){
MoveVehicle();
// transform.Rotate(-90f,0,0,Space.Self);
}
private void MoveVehicle(){
if (pathChoice == 0){
if (wayIndex <= waypoints.Length - 1){
target = waypoints[wayIndex].position;
Vector3 velocity = (target - transform.position).normalized * speed;
Vector3 seekForce = seek(target);
steering = steering + seekForce;
Vector3 finalVel = (velocity + steering);
// transform.position = Vector3.MoveTowards(transform.position,target,speed * Time.deltaTime);
transform.position = transform.position + finalVel * Time.deltaTime;
transform.LookAt(target);
// var targetRotation = Quaternion.LookRotation(target- transform.position);
// transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, speed * Time.deltaTime);
if (transform.position == waypoints[wayIndex].transform.position){
wayIndex += 1;
}
if (transform.position == waypoints[waypoints.Length - 1].position){
speed = 0.0f;
}
}
}else if (pathChoice == 1){
if (wayIndex <= waypoints2.Length - 1){
target = waypoints2[wayIndex].position;
transform.position = Vector3.MoveTowards(transform.position,target,speed * Time.deltaTime);
// var targetRotation = Quaternion.LookRotation(target- transform.position);
// transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, speed * Time.deltaTime);
transform.LookAt(target);
if (transform.position == waypoints2[wayIndex].transform.position){
wayIndex += 1;
}
if (transform.position == waypoints2[waypoints2.Length - 1].position){
speed = 0.0f;
vehicle.GetComponent<Follower>().enabled = false;
vehicle.GetComponent<Collisions>().enabled = false;
Destroy(vehicle);
}
}
}
}
private Vector3 seek(Vector3 target){
Vector3 vel = (target - transform.position).normalized * speed;
Vector3 desiredVel = (target - transform.position).normalized * speed;
Vector3 steeringForce = desiredVel - vel;
return steeringForce;
}
}
Two issues I see
You are moving your object using
transform.position = transform.position + finalVel * Time.deltaTime;
So it might happen that this overshoots the target so the check
if (transform.position == waypoints[wayIndex].transform.position)
which uses a precision range of 0.00001 never becomes true.
Before this didn't happen because MoveTowards prevents any overshooting.
You will need to use a certain range and rather approximately check
if(Vector3.Distance(transform.position, waypoints[wayIndex].transform.position) <= THRESHOLD)
where THRESHOLD needs to be a range big enough to not to be overshooten by finalVel => Something greater than the maximum finalVel magnitude
In
Vector3 vel = (target - transform.position).normalized * speed;
Vector3 desiredVel = (target - transform.position).normalized * speed;
Vector3 steeringForce = desiredVel - vel;
you store and substract the exact same vector .. your steeringForce is doomed to be always 0,0,0!
My objective here is to have a smoothed out "follow camera", for my space-fighter proof of concept game. The camera should match roll off the target object in all axis.
To that end I've "stolen" and modified this code from the unity Answers-site, and it works beautifully for X and Y (pitch and yaw), but it refuses to roll.
Code:
public float Distance;
public float Height;
public float RotationDamping;
public GameObject Target;
void LateUpdate()
{
var wantedRotationAngleYaw = Target.transform.eulerAngles.y;
var currentRotationAngleYaw = transform.eulerAngles.y;
var wantedRotationAnglePitch = Target.transform.eulerAngles.x;
var currentRotationAnglePitch = transform.eulerAngles.x;
var wantedRotationAngleRoll = Target.transform.eulerAngles.z;
var currentRotationAngleRoll = transform.eulerAngles.z;
currentRotationAngleYaw = Mathf.LerpAngle(currentRotationAngleYaw, wantedRotationAngleYaw, RotationDamping * Time.deltaTime);
currentRotationAnglePitch = Mathf.LerpAngle(currentRotationAnglePitch, wantedRotationAnglePitch, RotationDamping * Time.deltaTime);
currentRotationAngleRoll = Mathf.LerpAngle(currentRotationAngleRoll, wantedRotationAngleRoll, RotationDamping * Time.deltaTime);
var currentRotation = Quaternion.Euler(currentRotationAnglePitch, currentRotationAngleYaw, currentRotationAngleRoll);
transform.position = Target.transform.position;
transform.position -= currentRotation * Vector3.forward * Distance;
transform.LookAt(Target.transform);
transform.position += transform.up * Height;
}
Image:
I would be more certain about this answer if you explained what you were trying to do, but you should consider moving by Height in the direction of currentRotation * Vector3.up instead of transform.up. Also, consider using currentRotation * Vector3.up to set the local up direction when calling LookAt:
transform.position = Target.transform.position;
transform.position -= currentRotation * Vector3.forward * Distance;
Vector3 currentUp = currentRotation * Vector3.up;
transform.LookAt(Target.transform, currentUp);
transform.position += currentUp * Height;
I created a FPS Movement script in unity3d for bunny hopping with references from there, but I have some issues.When I am strafing fast my speed decreases.
I wanted to create something like this
This is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour {
//Strafe Variables
public float gravity = 3f;
public float ground_accelerate = 50f;
public float max_velocity_ground = 4f;
public float air_accelerate = 150f;
public float max_velocity_air = 2f;
public float friction = 8;
bool onGround;
public float jump_force = 5f;
private Vector3 lastFrameVelocity = Vector3.zero;
public Camera camObj;
Rigidbody rb;
Collider coll;
void Start () {
rb = GetComponent<Rigidbody> ();
coll = GetComponent<Collider> ();
}
void Update () {
Vector2 input = new Vector2 (Input.GetAxis ("Horizontal"), Input.GetAxis ("Vertical"));
Vector3 tempVelocity = CalculateFriction(rb.velocity);
tempVelocity += CalculateMovement (input, tempVelocity);
rb.velocity = tempVelocity;
lastFrameVelocity = rb.velocity;
rb.velocity += new Vector3(0f,-gravity,0f) * Time.deltaTime;
}
public Vector3 CalculateFriction(Vector3 currentVelocity)
{
onGround = Grounded();
float speed = currentVelocity.magnitude;
//Code from https://flafla2.github.io/2015/02/14/bunnyhop.html
if (!onGround || Input.GetButton("Jump") || speed == 0f)
return currentVelocity;
float drop = speed * friction * Time.deltaTime;
return currentVelocity * (Mathf.Max(speed - drop, 0f) / speed);
}
//Do movement input here
public Vector3 CalculateMovement(Vector2 input, Vector3 velocity)
{
onGround = Grounded();
//Different acceleration values for ground and air
float curAccel = ground_accelerate;
if (!onGround)
curAccel = air_accelerate;
//Ground speed
float curMaxSpeed = max_velocity_ground;
//Air speed
if (!onGround)
curMaxSpeed = max_velocity_air;
//Get rotation input and make it a vector
Vector3 camRotation = new Vector3(0f, camObj.transform.rotation.eulerAngles.y, 0f);
Vector3 inputVelocity = Quaternion.Euler(camRotation) *
new Vector3(input.x * air_accelerate, 0f, input.y * air_accelerate);
//Ignore vertical component of rotated input
Vector3 alignedInputVelocity = new Vector3(inputVelocity.x, 0f, inputVelocity.z) * Time.deltaTime;
//Get current velocity
Vector3 currentVelocity = new Vector3(velocity.x, 0f, velocity.z);
//How close the current speed to max velocity is (1 = not moving, 0 = at/over max speed)
float max = Mathf.Max(0f, 1 - (currentVelocity.magnitude / curMaxSpeed));
//How perpendicular the input to the current velocity is (0 = 90°)
float velocityDot = Vector3.Dot(currentVelocity, alignedInputVelocity);
//Scale the input to the max speed
Vector3 modifiedVelocity = alignedInputVelocity*max;
//The more perpendicular the input is, the more the input velocity will be applied
Vector3 correctVelocity = Vector3.Lerp(alignedInputVelocity, modifiedVelocity, velocityDot);
//Apply jump
correctVelocity += GetJumpVelocity(velocity.y);
//Return
return correctVelocity;
}
private Vector3 GetJumpVelocity(float yVelocity)
{
Vector3 jumpVelocity = Vector3.zero;
//Calculate jump
if ( Input.GetButton("Jump") && yVelocity < jump_force && Grounded())
{
jumpVelocity = new Vector3(0f, jump_force - yVelocity, 0f);
}
return jumpVelocity;
}
bool Grounded(){
return Physics.Raycast (transform.position, Vector3.down, coll.bounds.extents.y + 0.1f);
}
}
I have the following orbit script working just fine, on a GameObject in Unity3d. I want to have the script run on the GameObject if a GUI.Button is touched on Android device.
Here is the original C# orbir script:
using UnityEngine;
using System.Collections;
public class Orbiter : MonoBehaviour {
GameObject cube;
public Transform center;
public Vector3 axis = Vector3.up;
public Vector3 desiredPosition;
public float radius = 2.0f;
public float radiusSpeed = 0.5f;
public float rotationSpeed = 80.0f;
void Start () {
cube = GameObject.FindWithTag("MarkerObject");
center = cube.transform;
transform.position = (transform.position - center.position).normalized * radius + center.position;
radius = 2.0f;
}
void Update () {
transform.RotateAround (center.position, axis, rotationSpeed * Time.deltaTime);
desiredPosition = (transform.position - center.position).normalized * radius + center.position;
transform.position = Vector3.MoveTowards(transform.position, desiredPosition, Time.deltaTime * radiusSpeed);
}
}
Here is the modified code that refuses to run, no matter what I've tried.
using UnityEngine;
using System.Collections;
public class Orbiter : MonoBehaviour {
private bool IsOrbited = false;
private bool MustOrbit = false;
GameObject cube;
public Transform center;
public Vector3 axis = Vector3.up;
public Vector3 desiredPosition;
public float radius = 2.0f;
public float radiusSpeed = 0.5f;
public float rotationSpeed = 80.0f;
public Texture btnTexture2;
void Start () {
cube = GameObject.FindWithTag("MarkerObject");
center = cube.transform;
transform.position = (transform.position - center.position).normalized * radius + center.position;
radius = 2.0f;
}
// Update is called once per frame
void Update () {
if (MustOrbit && !IsOrbited) {
//Rotate all models around X,Y,Z axe
if (cube != null)
transform.RotateAround (center.position, axis, rotationSpeed * Time.deltaTime);
desiredPosition = (transform.position - center.position).normalized * radius + center.position;
transform.position = Vector3.MoveTowards(transform.position, desiredPosition, Time.deltaTime * radiusSpeed);
IsOrbited = true;
MustOrbit = false;
}
}
void OnGUI() {
GUI.matrix = Matrix4x4.TRS(Vector2.zero, Quaternion.identity,new Vector3(Screen.width / 480.0f, Screen.height / 320.0f, 1));
if (!btnTexture2) {
Debug.LogError("Please assign a texture on the inspector");
return;
}
//GUI.color = new Color(0,0,0,0);
//GUI.backgroundColor = Color.clear;
if (GUI.Button(new Rect(10, 10, 120, 30), btnTexture2))
if (!IsOrbited) {
MustOrbit = true;
}
}
}
What have I done wrong in coding? I get compiled o.k. Please advise.
Thank you all in advace for your answers.
inside your if statement you are disabling the block from running after 1 iteration resulting in barely any movement, try to comment out disabling the booleans so it can run
if (MustOrbit && !IsOrbited) {
//Rotate all models around X,Y,Z axe
if (cube != null)
transform.RotateAround (center.position, axis, rotationSpeed * Time.deltaTime);
desiredPosition = (transform.position - center.position).normalized * radius + center.position;
transform.position = Vector3.MoveTowards(transform.position, desiredPosition, Time.deltaTime * radiusSpeed);
// IsOrbited = true;
// MustOrbit = false;
}
to reset the x,y,z on your model in your start get the starting xyz as a vector3
public Vector3 reset;
in Start()
void Start () {
cube = GameObject.FindWithTag("MarkerObject");
center = cube.transform;
transform.position = (transform.position - center.position).normalized * radius + center.position;
radius = 2.0f;
reset = transform.position;
}
then onGUI()
void OnGUI() {
GUI.matrix = Matrix4x4.TRS(Vector2.zero, Quaternion.identity,new Vector3(Screen.width / 480.0f, Screen.height / 320.0f, 1));
if (!btnTexture2) {
Debug.LogError("Please assign a texture on the inspector");
return;
}
//GUI.color = new Color(0,0,0,0);
//GUI.backgroundColor = Color.clear;
if (GUI.Button(new Rect(10, 10, 120, 30), btnTexture2))
if (!IsOrbited) {
MustOrbit = true;
}
}
if(GUI.Button(new Rect(Screen.width*5/6,Screen.height*5/6,Screen.width/6,Screen.height/6),"reset")){
transform.position = reset;
}