I have an object called Ball, and I added keyboard interactivity to it(WASD to move the ball)
I need the camera to stay behind and follow the ball, but I am getting errors.
using UnityEngine;
using System.Collections;
public class ballmain : MonoBehaviour {
public bool isMoving = false;
public string direction;
public float camX;
public float camY;
public float camZ;
// Use this for initialization
void Start () {
Debug.Log("Can this run!!!");
}
// Update is called once per frame
void Update () {
camX = rigidbody.transform.position.x -=10;
camY = rigidbody.transform.position.y -=10;
camZ = rigidbody.transform.position.z;
camera.transform.position = new Vector3(camX, camY, camZ);
//followed by code that makes ball move
}
}
I get error "Assets/ballmain.cs(18,44): error CS1612: Cannot modify a value type return value of 'UnityEngine.Transform.position'. Consider storing the value in a temporary variable"
Does anyone know the answer? If I comment out the code about the camera the ball can move around.
here you go . a full code.
Simple Following
using UnityEngine;
using System.Collections;
public class Follow: MonoBehaviour {
public Transform target;
public float smooth= 5.0f;
void Update (){
transform.position = Vector3.Lerp (
transform.position, target.position,
Time.deltaTime * smooth);
}
}
Advanced Following
using UnityEngine;
using System.Collections;
public class SmoothFollowScript: MonoBehaviour {
// The target we are following
public Transform target;
// The distance in the x-z plane to the target
public int distance = 10.0;
// the height we want the camera to be above the target
public int height = 10.0;
// How much we
public heightDamping = 2.0;
public rotationDamping = 0.6;
void LateUpdate (){
// Early out if we don't have a target
if (TargetScript.russ == true){
if (!target)
return;
// Calculate the current rotation angles
wantedRotationAngle = target.eulerAngles.y;
wantedHeight = target.position.y + height;
currentRotationAngle = transform.eulerAngles.y;
currentHeight = transform.position.y;
// Damp the rotation around the y-axis
currentRotationAngle = Mathf.LerpAngle (currentRotationAngle, wantedRotationAngle, rotationDamping * Time.deltaTime);
// Damp the height
currentHeight = Mathf.Lerp (currentHeight, wantedHeight, heightDamping * Time.deltaTime);
// Convert the angle into a rotation
currentRotation = Quaternion.Euler (0, currentRotationAngle, 0);
// Set the position of the camera on the x-z plane to:
// distance meters behind the target
transform.position = target.position;
transform.position -= currentRotation * Vector3.forward * distance;
// Set the height of the camera
transform.position.y = currentHeight;
// Always look at the target
transform.LookAt (target);
}
}
}
If you just simply want to follow the target object align the position of the camera the way you want it and make the camera the child of the target object and the rest will do
Here're one script I found useful during my game development. I didn't create them so I give credit to wiki.unity3d.com for providing this amazing script.
Smooth Follow:
using UnityEngine;
using System.Collections;
public class SmoothFollow2 : MonoBehaviour {
public Transform target;
public float distance = 3.0f;
public float height = 3.0f;
public float damping = 5.0f;
public bool smoothRotation = true;
public bool followBehind = true;
public float rotationDamping = 10.0f;
void Update () {
Vector3 wantedPosition;
if(followBehind)
wantedPosition = target.TransformPoint(0, height, -distance);
else
wantedPosition = target.TransformPoint(0, height, distance);
transform.position = Vector3.Lerp (transform.position, wantedPosition, Time.deltaTime * damping);
if (smoothRotation) {
Quaternion wantedRotation = Quaternion.LookRotation(target.position - transform.position, target.up);
transform.rotation = Quaternion.Slerp (transform.rotation, wantedRotation, Time.deltaTime * rotationDamping);
}
else transform.LookAt (target, target.up);
}
}
More information about my work
Include Standard Mobile Asset to your project. It contains a SmoothFollow2D.js code in its script section. Attach this code with the gameobject and initialize public variables. This will simply do the job for you.
I found this simple and useful unity 2d camera follow script.
using UnityEngine;
using System.Collections;
public class FollowCamera : MonoBehaviour {
public float interpVelocity;
public float minDistance;
public float followDistance;
public GameObject target;
public Vector3 offset;
Vector3 targetPos;
// Use this for initialization
void Start () {
targetPos = transform.position;
}
// Update is called once per frame
void FixedUpdate () {
if (target)
{
Vector3 posNoZ = transform.position;
posNoZ.z = target.transform.position.z;
Vector3 targetDirection = (target.transform.position - posNoZ);
interpVelocity = targetDirection.magnitude * 5f;
targetPos = transform.position + (targetDirection.normalized * interpVelocity * Time.deltaTime);
transform.position = Vector3.Lerp( transform.position, targetPos + offset, 0.25f);
}
}
}
source unity2d camera follow script
The -= in these lines:
camX = rigidbody.transform.position.x -=10;
camY = rigidbody.transform.position.y -=10;
is wrong. The -= will attempt to modify the rigidbody.transform.position. You just want -.
However, as it stands, the camera won't track changes in the target's Z position, nor will it track properly if the camera is rotated. To get the correct position you need (in vectors):-
cam_pos = target_pos - dist_to_target * cam_look_at
Related
Im making a game where you click and drag with the mouse then release to launch the player. But sometimes the player gets launched in the opposite direction of where it should go. I made a debug output to show you the different values. Here is the output
In that image for example you can see that the Vector2 of force * power is positive on the y axis, but the player launched downwards, and the same happens Viceversa. I think its also worth to note that this happens inconsistantly for some reason. Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
public GameObject player;
public float power = 10f;
public Rigidbody2D rb;
public float maxSpeed;
public Vector2 minPower;
public Vector2 maxPower;
TragectoryLine tl;
Camera cam;
public Vector2 force;
public Vector3 startPoint;
public Vector3 endPoint;
public Vector3 currentPoint;
public Vector3 startPointMouse;
public bool isPulling = false;
float distance;
private void Start()
{
cam = Camera.main;
tl = GetComponent<TragectoryLine>();
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
startPointMouse = cam.ScreenToWorldPoint(Input.mousePosition);
startPointMouse.z = 15;
}
if (Input.GetMouseButton(0))
{
startPoint = player.transform.position;
startPoint.z = 15;
isPulling = true;
Vector3 currentPoint = cam.ScreenToWorldPoint(Input.mousePosition);
currentPoint.z = 15;
tl.RenderLine(startPoint, currentPoint);
}
if (Input.GetMouseButtonUp(0))
{
endPoint = cam.ScreenToWorldPoint(Input.mousePosition);
endPoint.z = 15;
isPulling = false;
tl.EndLine();
distance = startPointMouse.magnitude - endPoint.magnitude;
if (distance < 0)
{
distance = -distance;
}
if (distance >= 1)
{
rb.AddForce(force * power, ForceMode2D.Impulse);
}
force = new Vector2(Mathf.Clamp(startPoint.x - endPoint.x, minPower.x, maxPower.x), Mathf.Clamp(startPoint.y - endPoint.y, minPower.y, maxPower.y));
Debug.Log("distance" + distance);
Debug.Log("start" + startPoint);
Debug.Log("end" + endPoint);
Debug.Log("force" +force);
Debug.Log("force * power" + force * power);
}
}
private void FixedUpdate()
{
rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxSpeed);
}
}
Here I added the force using rb.AddForce(force * power, ForceMode2D.Impulse); when the force * power value was positive on the y axis. So why did it go to the opposite direction???
This was working perfectly fine before i tried implementing a feature where the player has to move the mouse a certain distance or else it wont launch. I have tried removing it but it doesnt seem to make a difference. I think I changed something in the code that ruined it but I cant figure out what! Please help!
Should I use Cinemachine for that or it's better to do it with a script from scratch ?
The script is attached to the Main Camera.
Now it's orbit only left right. I want it to orbit 360 degrees with clamp so it wont move down to the floor and to up back.
I should also the Y and not only the X but not sure how.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerFollow : MonoBehaviour {
public Transform PlayerTransform;
private Vector3 _cameraOffset;
[Range(0.01f, 1.0f)]
public float SmoothFactor = 0.5f;
public bool LookAtPlayer = false;
public bool RotateAroundPlayer = true;
public float RotationsSpeed = 5.0f;
// Use this for initialization
void Start () {
_cameraOffset = transform.position - PlayerTransform.position;
}
// LateUpdate is called after Update methods
void LateUpdate () {
if(RotateAroundPlayer)
{
Quaternion camTurnAngle =
Quaternion.AngleAxis(Input.GetAxis("Mouse X") * RotationsSpeed, Vector3.up);
_cameraOffset = camTurnAngle * _cameraOffset;
}
Vector3 newPos = PlayerTransform.position + _cameraOffset;
transform.position = Vector3.Slerp(transform.position, newPos, SmoothFactor);
if (LookAtPlayer || RotateAroundPlayer)
transform.LookAt(PlayerTransform);
}
}
I'm creating a 2D horizontal side-scroller and I have enemies being spawned whose rigidbody component is being used to give them a velocity like so:
using UnityEngine;
using System.Collections;
public class Mover : MonoBehaviour
{
public float speed;
public new Rigidbody2D rigidbody;
public bool random;
void Start()
{
if (random) {
rigidbody.velocity = Random.value * transform.right * speed;
}
else
{
rigidbody.velocity = transform.right * speed;
}
}
}
How can I have these enemies also move up and down constantly on the the Y-axis while they are moving with a velocity on the X-axis? Everything I have tried seems to interfere with the velocity of the objects. I am basically trying to create a simple behavioral pattern so as to make the targets harder for the player to aim at.
Any ideas?
This is just a starting point, but you would have to experiment with different ways to do it to get the behavior you want. Maybe you can try using rigidbody.AddForce too.
If you haven't already, I recommend watching the video tutorials for the 2D platformer.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
public class Mover : MonoBehaviour {
public float speed, waveSpeed;
new Rigidbody2D rigidbody;
public bool random;
// Use this for initialization
void Start () {
rigidbody = GetComponent<Rigidbody2D>();
if (random) {
rigidbody.velocity = Random.value * transform.right * speed;
} else {
rigidbody.velocity = transform.right * speed;
}
}
float angle = 0;
// Use this for physics calculations
void FixedUpdate () {
var wave = Mathf.Sin(angle += waveSpeed); // goes from -1 to +1
var p = rigidbody.position;
p.y = wave; // or: yCenter + yHeight * wave
rigidbody.position = p;
}
}
I have found the solution by following the answer given under this link: https://gamedev.stackexchange.com/questions/96878/how-to-animate-objects-with-bobbing-up-and-down-motion-in-unity?newreg=ccb2eaf1b725413ca777a68348637990
Here is my updated code:
public class EnemyMover : MonoBehaviour {
public float speed;
public new Rigidbody2D rigidbody;
public bool random;
float originalY;
public float floatStrength = 1;
void Start()
{
this.originalY = this.transform.position.y;
if (random) {
rigidbody.velocity = Random.value * transform.right * speed;
}else
{
rigidbody.velocity = transform.right * speed;
}
}
void Update()
{
transform.position = new Vector3(transform.position.x,
originalY + ((float)System.Math.Sin(Time.time) * floatStrength),
transform.position.z);
}
}
I am messing around in Unity and wanted to make a mechanic where a box would touch another object and then that object would follow the Player.
I have Cube set up like this:
And a Sphere with a Box Collider with same options.
My Player script is thus:
public class Player : MonoBehaviour {
public float speed = 0.0f;
public float moveX = 0.0f;
public float moveY = 0.0f;
public GameObject player;
public GameObject obj;
//public float force = 0.0f;
private bool collided = false;
// Use this for initialization
void Start () {
player = GameObject.FindWithTag ("Player");
}
// Update is called once per frame
void FixedUpdate () {
moveX = Input.GetAxis ("Horizontal");
moveY = Input.GetAxis ("Vertical");
player.GetComponent<Rigidbody> ().velocity = new Vector2 (moveX * speed, moveY * speed);
}
void OnCollisionEnter (Collision col) {
if (col.gameObject == obj) {
collided = true;
}
}
void OnCollisionExit (Collision col) {
if (col.gameObject == obj) {
collided = false;
}
}
void Update () {
if(collided) {
obj.transform.position = (player.transform.position - obj.transform.position)*speed;
}
}
}
What have I yet to do? Hoping someone can nudge me in the right direction.
I will provide you two scripts.
1st Script is FollowTarget. This will follow your target forcely.
2nd Script is SmoothFollow which will follow your target in a smooth movement.
FollowTarget.cs
using System;
using UnityEngine;
public class FollowTarget : MonoBehaviour
{
public Transform target;
public Vector3 offset = new Vector3(0f, 7.5f, 0f);
private void LateUpdate()
{
transform.position = target.position + offset;
}
}
SmoothFollow.cs
using UnityEngine;
public class SmoothFollow : MonoBehaviour
{
// The target we are following
[SerializeField]
private Transform target;
// The distance in the x-z plane to the target
[SerializeField]
private float distance = 10.0f;
// the height we want the camera to be above the target
[SerializeField]
private float height = 5.0f;
[SerializeField]
private float rotationDamping;
[SerializeField]
private float heightDamping;
// Use this for initialization
void Start() { }
// Update is called once per frame
void LateUpdate()
{
// Early out if we don't have a target
if (!target)
return;
// Calculate the current rotation angles
var wantedRotationAngle = target.eulerAngles.y;
var wantedHeight = target.position.y + height;
var currentRotationAngle = transform.eulerAngles.y;
var currentHeight = transform.position.y;
// Damp the rotation around the y-axis
currentRotationAngle = Mathf.LerpAngle(currentRotationAngle, wantedRotationAngle, rotationDamping * Time.deltaTime);
// Damp the height
currentHeight = Mathf.Lerp(currentHeight, wantedHeight, heightDamping * Time.deltaTime);
// Convert the angle into a rotation
var currentRotation = Quaternion.Euler(0, currentRotationAngle, 0);
// Set the position of the camera on the x-z plane to:
// distance meters behind the target
transform.position = target.position;
transform.position -= currentRotation * Vector3.forward * distance;
// Set the height of the camera
transform.position = new Vector3(transform.position.x ,currentHeight , transform.position.z);
// Always look at the target
transform.LookAt(target);
}
}
Just choose one of them and then attach it to the gameObject. Like another box that is suppose to follow.
Remove your Update() function in your script as you don't need it anymore.
Also Remove your OnCollisionExit()
void OnCollisionEnter (Collision col) {
if (col.gameObject == obj) {
// If you choose to use SmoothFollow Uncomment this.
//col.GetComponent<SmoothFollow>().target = this.transform;
// If you choose to use FollowTarget Uncomment this
//col.GetComponent<FollowTarget>().target = this.transform;
}
}
This is Player script:
public class player
{ public projectile pro;
pro = GetComponent<projectile>();
void Update()
{
GameObject go = GameObject.Find("enemy");
Transform playerTransform = go.transform;
Vector3 posi = playerTransform.position;
pro.Target = posi; // getting error here
Instantiate(bulletprefab, position, Quaternion.identity);
}
}
This is Projectile Script:
Requirement: Get updated position of Target in Projectile but since projectileMotion() method is being called from Start() and I want the Target current's position at point when Instantiate is called in Player so as to calculate the Target_Distance appropriately in Projectile class,
But looks like the assignment from a Vector3 to _pro.Target which is a vector3 only is not allowed. Ho can I fix this?
public class projectile : MonoBehaviour
{
public Vector3 Target;
public GameObject bulletprefab;
public float firingAngle = 45.0f;
public float gravity = 9.8f;
public Transform Projectile;
private Transform myTransform;
void Awake()
{
myTransform = transform;
}
void Start()
{ myTransform.LookAt(Target);
StartCoroutine (ProjectileMotion ());
}
IEnumerator ProjectileMotion()
{
yield return new WaitForSeconds(0.25f);
Projectile.position = myTransform.position + new Vector3(0, 0.0f, 0);
// Calculating distance to target
float target_Distance = Vector3.Distance(Projectile.position, Target );
Debug.Log ("realUPDATEDOR not" + Target);
float projectile_Velocity = target_Distance / (Mathf.Sin(2 * firingAngle* Mathf.Deg2Rad) / gravity);
// X Y componenent of the velocity
float Vx = Mathf.Sqrt(projectile_Velocity) * Mathf.Cos(firingAngle * Mathf.Deg2Rad);
float Vy = Mathf.Sqrt(projectile_Velocity) * Mathf.Sin(firingAngle * Mathf.Deg2Rad);
// flight time since depends on horizontal component of velocity
float flightDuration = target_Distance / Vx;
// projectile rotated at target
Projectile.rotation = Quaternion.LookRotation(Target - Projectile.position);
float elapse_time = 0;
while (elapse_time < flightDuration) //looping and incrementing elapsed time
{
Projectile.Translate(0, (Vy - (gravity * elapse_time)) * Time.deltaTime, Vx * Time.deltaTime);
elapse_time += Time.deltaTime;
yield return null;
}
}
}
Target is present is Projectile class and is Vector3 only, how to fix this error?
the code you get a reference to the "projectile" script wont work.
change :
public projectile pro;
pro = GetComponent<projectile>();
to something like this:
public projectile pro;
void Start()
{
pro = GetComponent<projectile>();
}
Also as a suggestion you might wanna reduce the GameObject.Find uses inside the update function cause of its high cost.