I have created a walking character in Unity 3D and I watched a tutorial to make a script that makes the player follow the camera which is good but I want the camera to be lower done and to be rotated more backwards so that the camera can see more of the world as right now not much is visible passed the player. I have attached a link to an image of what it looks like now.
https://i.imgur.com/jQ6efAJ.png
as you can see you can't see much of what's in front of the player.
Next I will attach the script and hopefully you can show me what code needs adding or changing to allow my changes to be possible.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
public Transform playerObject;
public float distanceFromObject = 6f;
void Update()
{
Vector3 lookOnObject = playerObject.position - transform.position;
lookOnObject = playerObject.position - transform.position;
transform.forward = lookOnObject.normalized;
Vector3 playerLastPosition;
playerLastPosition = playerObject.position - lookOnObject.normalized * distanceFromObject;
playerLastPosition.y = playerObject.position.y + distanceFromObject / 2;
transform.position = playerLastPosition;
}
Thank you in advance for helping me. This is for a school project so I really hope that your solutions are great and can't wait to hear from you!
You're looking into adding an offset to the camera relative to the look position of the camera. What you need to do is to offset the playerObject.position when you assign it to the lookOnObject.
Add a new vector3 and call it as an lookOffset. It will now become lookOnObject = (playerObject.position + lookOffset) - transform.position. It will act as a pitch control for your camera.
Use distanceFromObject to control the z position of the camera.
[EDIT]
Here's the altered script that I made. As mentioned above, you need to offset the position that the camera will look to. In this script, instead of a Vector3, I used float:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;`
public class CameraFollow : MonoBehaviour
{
public Transform playerObject;
//Controls the pitch of the camera where it rotates
//in X axis
public float pitchOffset = 0;
//Controls the yaw of the camera where it rotates
//in Y axis
public float yawOffset = 0;
public float distanceFromObject = 6f;
void Update()
{
//Creation of the look offset relative to the
//Observable position
Vector3 lookOffset = playerObject.position;
lookOffset.y += pitchOffset;
lookOffset.x += yawOffset;
Vector3 lookOnObject = playerObject.position - transform.position;
//Replaced playerObject.position with lookOffset
lookOnObject = lookOffset - transform.position;
transform.forward = lookOnObject.normalized;
Vector3 playerLastPosition;
//Replaced playerObject.position with lookOffset
playerLastPosition = lookOffset - lookOnObject.normalized * distanceFromObject;
playerLastPosition.y = playerObject.position.y + distanceFromObject / 2;
transform.position = playerLastPosition;
}
}
It could be done with Vector3 or Vector2 where you store the pitchOffset, and yawOffset to x and y fields.
Related
First of all, I am EXTREMELY new to coding in general, but I've picked it up as a hobby, so please forgive my general lack of understanding.
I am putting together a sidescrolling platformer, in which a small character follows you around and gives you advice, lights the way, fills in lore, etc. Think Navi from Legend of Zelda. I already have a functioning script for following the player around, which I will post below.
However, I cannot get it to then lazily float around the character rather than just sitting still.
public class WillOWispFollowPlayer : MonoBehaviour
{
public Transform target;
public float smoothSpeed = 0.05f;
public Vector3 offset;
private void FixedUpdate()
{
Vector3 desiredPosition = target.position + offset;
Vector3 smoothedPosition = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed);
transform.position = smoothedPosition;
}
}
I haven't dabbled to far into game development, but how I would go about it is to implement some random location with a bias towards the player or a target position near the player.
So, say that at semi even intervals, you generate a new random position or direction for your companion to move towards to, the distance should be relatively close to the companions current location. To prevent your companion randomly flying off, into the sunset, you should also make sure that this random location or direction is biased towards the players location, for example, the further away it is from the player, the more biased it will be to move towards the player.
After hammering away at this for a while, and looking at some other people's code, this is what I've come up with. It adds two functions to the original code. One is a random direction function with adjustable acceleration and deceleration which is applied in FixedUpdate. The other is a short burst of velocity in a separate random direction. The effect is more fluttery than I originally intended, and less of a floaty wander effect, but it works. If anyone has any ideas to make this a less jittery and more smooth, floaty effect, Im open to suggestions.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
public class WillOWispFollowPlayer : MonoBehaviour
{
public Transform target;
public float smoothSpeed = 0.05f;
public float smoothSpeedSlow = 0.02f;
public Vector3 offset;
public float hoverSpeed = 10000f;
public Rigidbody2D rb;
public static System.Timers.Timer hoverTimer;
public float acceleration;
public float deceleration;
private Rigidbody2D physics;
private Vector2 direction;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
InvokeRepeating("HoverDirection", 0, 1); //calling the DoverDirection every second
physics = GetComponent<Rigidbody2D>();
physics.gravityScale = 0;
physics.drag = deceleration;
}
private void FixedUpdate()
{
Vector3 desiredPosition = target.position + offset;
Vector3 smoothedPosition = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed);
Vector3 smoothedPositionSlow = Vector3.Lerp(transform.position, desiredPosition, smoothSpeedSlow);
//setting up a "wander zone" where the Will'o'the'Wisp is less restricted within a defined distance of the player
if (Vector3.Distance((target.position + offset), this.transform.position) >= .5)
{
transform.position = smoothedPosition;
}
else
{
transform.position = smoothedPositionSlow;
}
//Random direction generator This results in a "flutter" effect
direction = UnityEngine.Random.insideUnitCircle;
Vector2 directionalForce = direction * acceleration;
physics.AddForce(directionalForce * Time.deltaTime, ForceMode2D.Impulse);
}
//A regular and prominant directional change, resulting in short darting motions around the target position
void HoverDirection()
{
rb.velocity = Random.onUnitSphere * hoverSpeed;
}
}
I want to change the position of the object to the position of the mouse, moving slowly from first to second position.
My object is moving slowly to the random direction which appears to be connected with lower-left corner. When I go higher than the corner my object is moving upwards, same with left and right.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rocket : MonoBehaviour
{
public float speed = 10f;
private Vector3 shippos;
void Start()
{
shippos = transform.position;
}
void FixedUpdate()
{
if (Input.mousePosition.x > shippos.x)
shippos.x=shippos.x+speed*Time.deltaTime;
if (Input.mousePosition.x < shippos.x)
shippos.x=shippos.x-speed*Time.deltaTime;
if (Input.mousePosition.y > shippos.y)
shippos.y=shippos.y+speed*Time.deltaTime;
if (Input.mousePosition.y < shippos.y)
shippos.y=shippos.y-speed*Time.deltaTime;
transform.position = shippos;
}
}
The mouse position is returned in screenspace coordinates. What you need to do is convert this to world coordinates so that they are compared in the same coordinate space as the transform (shippos).
void FixedUpdate()
{
if (Camera.main.ScreenToWorldPoint(Input.mousePosition).x > shippos.x)
shippos.x = shippos.x + speed * Time.deltaTime;
if (Camera.main.ScreenToWorldPoint(Input.mousePosition).x < shippos.x)
shippos.x = shippos.x - speed * Time.deltaTime;
if (Camera.main.ScreenToWorldPoint(Input.mousePosition).y > shippos.y)
shippos.y = shippos.y + speed * Time.deltaTime;
if (Camera.main.ScreenToWorldPoint(Input.mousePosition).y < shippos.y)
shippos.y = shippos.y - speed * Time.deltaTime;
transform.position = shippos;
}
If I did not misunderstand, you want to change your player's position straight to the point of mouse's position and looking towards mouse.
void Update() {
Transform target = mousePosition; //get your mouse position per frame
Vector3 relativePos = target.position - transform.position; //create a vector3 between them
Quaternion rotation = Quaternion.LookRotation(relativePos); //then give a rotation your player towards this vector.
transform.rotation = rotation; //and apply it.
}
Taken from here: http://answers.unity3d.com/questions/633873/how-to-make-an-object-move-towards-the-mouse-point.html
public float moveSpeed = 2.0; // Units per second
void Update () {
var targetPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
targetPos.z = transform.position.z;
transform.position = Vector3.MoveTowards(transform.position, targetPos, moveSpeed * Time.deltaTime);
}
May not be accurate C#, but you get the idea.
i guess you are doing wrong , because wile you have Mathf.Lerp you Dont need to go as that clumsy way
Here is a video tutorial from youtube for mathf.lerp
and here is the base code:
someValue = Mathf.Lerp(initialValue , finalValue , Time.deltaTime * smoothness);
just take a look to the youtube link you will definitely get the idea!
AS A SIDE NOTE
you dont need to do alot of stuff to decrease your game performance! be careful about this kinda coding!
I used This code for my MainCamera for following the player in my 2d game in Unity5 :
using UnityEngine;
using System.Collections;
public class CameraFollow : MonoBehaviour {
public float dampTime = 0.15f;
private Vector3 velocity = Vector3.zero;
public Transform target;
// Update is called once per frame
void Update ()
{
if (target)
{
Vector3 point = GetComponent<Camera>().WorldToViewportPoint(target.position);
Vector3 delta = target.position - GetComponent<Camera>().ViewportToWorldPoint(new Vector3(0.5f, 0.5f, point.z)); //(new Vector3(0.5, 0.5, point.z));
Vector3 destination = transform.position + delta;
transform.position = Vector3.SmoothDamp(transform.position, destination, ref velocity, dampTime);
}
}
}
It work fine But player is in middle of screen allways . i wan player be in down of screen and my sprite for show Earth of my game will stick below the camera . i mean better in following pictures:
What I Want :
The Result :
You can add a vertical offset to the calculation. Just adding it to destination should do that I think.
Vector3 destination = ...
destination.y += someOffset;
transform.position = Vector3.SmoothDamp(...);
Otherwise you could also add an empty gameobject to the player gameobject and use that as your target.
One thing that you might need to consider is the resolution.
I'm creating a Google Cardboard VR app in Unity. I want the camera to constantly move forwards horizontally in the direction the camera is facing but not change its Y position, i.e. not rise or fall.
I've managed to get it so that the camera moves forwards in whichever direction it's looking but can go up and down if you look that way, using this line of code:
transform.position = transform.position + cam.transform.forward * WalkingSpeed * Time.deltaTime;
Is there a simple way of fixing the Y axis, so that I get the behaviour I'm looking for? Here's the full code so far:
using UnityEngine;
using System.Collections;
public class CameraMovement : MonoBehaviour {
public float WalkingSpeed = 1.0f;
public bool WalkEnabled = true;
GameObject cam;
void Start () {
// This is the part of the Cardboard camera where I'm getting
// the forward position from:
cam = GameObject.FindWithTag("CCHead");
}
void Update ()
{
if (WalkEnabled)
{
walk();
}
}
void walk()
{
transform.localPosition = transform.localPosition + cam.transform.forward * WalkingSpeed * Time.deltaTime;
}
}
Note: ticking the 'freeze position' y value in rigidbody constraints doesn't work.
Many thanks in advance.
You can try and split the forward vector up and build a new one where the y axis does not change:
transform.position =
transform.position +
new Vector3(
cam.transform.forward.x * WalkingSpeed * Time.deltaTime,
0, // add 0 to keep the y coordinate the same
cam.transform.forward.z * WalkingSpeed * Time.deltaTime);
I'm using the standard camera2DFollow script that comes with Unity 5. But I have a problem with the position of the camera. I've rotated my main camera and it looks like this now.
You see that my player is on top of the screen instead of the middle.
This is the default script in C# for the people who don't have it.
using System;
using UnityEngine;
namespace UnityStandardAssets._2D
{
public class Camera2DFollow : MonoBehaviour
{
public Transform target;
public float damping = 1;
public float lookAheadFactor = 3;
public float lookAheadReturnSpeed = 0.5f;
public float lookAheadMoveThreshold = 0.1f;
private float m_OffsetZ;
private Vector3 m_LastTargetPosition;
private Vector3 m_CurrentVelocity;
private Vector3 m_LookAheadPos;
// Use this for initialization
private void Start()
{
m_LastTargetPosition = target.position;
m_OffsetZ = (transform.position - target.position).z;
transform.parent = null;
}
// Update is called once per frame
private void Update()
{
// only update lookahead pos if accelerating or changed direction
float xMoveDelta = (target.position - m_LastTargetPosition).x;
bool updateLookAheadTarget = Mathf.Abs(xMoveDelta) > lookAheadMoveThreshold;
if (updateLookAheadTarget)
{
m_LookAheadPos = lookAheadFactor*Vector3.right*Mathf.Sign(xMoveDelta);
}
else
{
m_LookAheadPos = Vector3.MoveTowards(m_LookAheadPos, Vector3.zero, Time.deltaTime*lookAheadReturnSpeed);
}
Vector3 aheadTargetPos = target.position + m_LookAheadPos + Vector3.forward*m_OffsetZ;
Vector3 newPos = Vector3.SmoothDamp(transform.position, aheadTargetPos, ref m_CurrentVelocity, damping);
transform.position = newPos;
m_LastTargetPosition = target.position;
}
}
}
I want to change the Y to a +3 of the current position. So if my camera is on Y 2 than put it on Y 5. (This makes it so the player is in the middle and not on the top).
Thanks for the help!
You can do this by adding 3 to the camera's position at the end of each frame but I recommend against it.
What I would do, is create an empty object, name it "PlayerCameraCenter" and make the player parent to this object; then place the camera center wherever you want relative to the player, like y = 3, and make the camera follow this object instead of the player.
This way you can easily change the position of the camera, through the editor without fiddling with code.