Ok im new to javascript and Unity so this is clearly a very noob beginner question.
Basically I have created a script that i place on my camera. Then when i select a model in the game it becomes the target of the camera script and im trying to make the camera smoothly turn to it. below is what im trying
in the update function i use raycast to catch a unit on the mouse click. this becomes the target variable in the script. it sets a bool to true then to follow target in the moveto function. but it only seems to move the camera if i keep the mouse left button pressed down on the unit. Im trying to select a unit then let the camera smoothly rotate to the unit.
Any ideas on this rookie mistake?
#pragma strict
var speed = 5.0;
var freeMovementTurnSpeed = 10.0;
var freeMovementForwardSpeed = 10.0;
var freeMovementVerticalSpeed = 10.0;
var maxHeight = 30;
var minHeight = 2;
var target : Transform;
var distance = 10.0;
var maxDistance = 50;
var minDistance = 10;
var xSpeed = 250.0;
var ySpeed = 120.0;
var yMinLimit = -20;
var yMaxLimit = 80;
private var x = 0.0;
private var y = 0.0;
// The distance in the x-z plane to the target
var followDistance = 30.0;
var maxDistanceDelta = 0.2;
var damping = 3.0;
var followTarget = false;
var smoothRotation ;
function Start () {
var angles = transform.eulerAngles;
x = angles.y;
y = angles.x;
if(target){
transform.LookAt(target);
}
// Make the rigid body not change rotation
if (rigidbody)
rigidbody.freezeRotation = true;
}
function LateUpdate () {
if(target){
if(followTarget){
moveTo();
}
else{
targetSelectedMovement();
}
}
else {
freeMovement();
}
}
function moveTo(){
//transform.LookAt (target);
var currentDistance = Vector3.Distance(transform.position,target.position);
//if (currentDistance<40){
//followTarget = false;
//}
//else{
smoothRotation = Quaternion.LookRotation(target.position - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, smoothRotation, Time.deltaTime * damping);
print(target);
//transform.position = Vector3.MoveTowards(transform.position,target.position,maxDistanceDelta);
//}
}
function freeMovement(){
var zPos = Input.GetAxis("Vertical") * Time.deltaTime * freeMovementForwardSpeed;
var xPos = Input.GetAxis("Horizontal") * Time.deltaTime * freeMovementTurnSpeed;
var strafePos = Input.GetAxis("Strafe")* Time.deltaTime * freeMovementForwardSpeed;
var vertPos = Input.GetAxis("GainVertical")* Time.deltaTime * freeMovementVerticalSpeed;
if (Input.GetButton("Fire2")) {
x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
y = ClampAngle(y, yMinLimit, yMaxLimit);
var rotation2 = Quaternion.Euler(y, x, 0);
transform.rotation = rotation2;
}
else {
transform.Rotate(0, Input.GetAxis("Horizontal")*freeMovementTurnSpeed*Time.deltaTime, 0,Space.World);
}
if (vertPos > 0 && transform.position.y > maxHeight){
vertPos = 0;
}
else if(vertPos < 0 && transform.position.y < minHeight){
vertPos = 0;
}
print(transform.position.y);
transform.Translate(strafePos,vertPos,zPos);
}
function targetSelectedMovement() {
if(Input.GetKey("a") || Input.GetKey("d") ){
x += (-Input.GetAxis("Horizontal")) * xSpeed * 0.02;
var rotation = Quaternion.Euler(y, x, 0);
var currentDistance = Vector3.Distance(transform.position,target.position);
var position = rotation * Vector3(0.0, 0.0, -currentDistance) + target.position;
transform.rotation = rotation;
transform.position = position;
}
var zPos = Input.GetAxis("Vertical") * Time.deltaTime * speed;
currentDistance = Vector3.Distance(transform.position,target.position);
if(currentDistance < maxDistance && zPos < 0){
transform.Translate(0, 0, zPos);
}
else if(currentDistance > minDistance && zPos > 0){
transform.Translate(0, 0, zPos);
}
if (Input.GetButton("Fire2")) {
x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
y = ClampAngle(y, yMinLimit, yMaxLimit);
var rotation2 = Quaternion.Euler(y, x, 0);
var currentDistance2 = Vector3.Distance(transform.position,target.position);
var position2 = rotation2 * Vector3(0.0, 0.0, -currentDistance2) + target.position;
transform.rotation = rotation2;
transform.position = position2;
}
}
static function ClampAngle (angle : float, min : float, max : float) {
if (angle < -360)
angle += 360;
if (angle > 360)
angle -= 360;
return Mathf.Clamp (angle, min, max);
}
function Update () {
var hit : RaycastHit;
if (Input.GetButton("Fire1")) {
var ray : Ray = Camera.main.ScreenPointToRay (Input.mousePosition);
// Cast a ray forward from our position for the specified distance
if (Physics.Raycast(ray, hit))
{
// Add a specified force to the Rigidbody component to the other GameObject
if(hit.collider.tag == "Unit"){
print("Selected " + hit.collider.gameObject.name);
target = hit.collider.gameObject.transform;
//transform.LookAt(target);
followTarget = true;
}
else {
target = null;
}
}
}
}
:)
Answer pulled from my comments above:
"I'll have to look when I get on my dev. machine but in the mean time try replacing Input.GetButton("Fire1") with Input.GetButtonDown("Fire1"). Just as a test, because looking at your code nothing jumps out at me. GetButton is true as long as the button is held, in the past I have had issues with it incorrectly triggering just as the mouse moved off an object."
Related
I'm trying to limit the zoom value of my game to a minimum and a maximum but i can't get how to do it!
I've been trying by limiting the Y according to the zoom factor but it does not work properly, because when it reaches the limit, it starts flickering, like it hit an obstacle. I found some things that can solve this problem by using the fieldofview, but I need it to work with the Y limitations!
I also want to add a panning limit, so that the player won't be able to see the end of the map but I didn't get there yet.
Anyways, here is the code i'm using and would appreciate if someone could help!
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
class ScrollAndPinch : MonoBehaviour
{
#if UNITY_IOS || UNITY_ANDROID
public Camera Camera;
public bool Rotate;
protected Plane Plane;
public float scrollSpeed;
public float rotateSpeed;
public float zoomSpeed;
public float zoomMinY;
public float zoomMaxY;
public float camsummer;
Vector3 pos;
private Vector3 velocity = Vector3.zero;
private void Awake()
{
if (Camera == null)
Camera = Camera.main;
Rotate = true;
scrollSpeed = 50f;
rotateSpeed = 50f;
zoomSpeed = 1f;
zoomMinY = 50f;
zoomMaxY = 200f;
camsummer = 0.1f;
pos = new Vector3(0f, 0f, 0f);
}
private void Update()
{
//Update Plane
if (Input.touchCount >= 1)
Plane.SetNormalAndPosition(transform.up, transform.position);
var Delta1 = Vector3.zero;
var Delta2 = Vector3.zero;
//Scroll
if (Input.touchCount == 1)
{
Delta1 = PlanePositionDelta(Input.GetTouch(0));
if (Input.GetTouch(0).phase == TouchPhase.Moved)
Camera.transform.Translate(Delta1 * scrollSpeed * Time.deltaTime, Space.World);
}
//Pinch
if (Input.touchCount == 2)
{
var pos1 = PlanePosition(Input.GetTouch(0).position);
var pos2 = PlanePosition(Input.GetTouch(1).position);
var pos1b = PlanePosition(Input.GetTouch(0).position - Input.GetTouch(0).deltaPosition);
var pos2b = PlanePosition(Input.GetTouch(1).position - Input.GetTouch(1).deltaPosition);
//calc zoom to be done relative to the distance moved between the fingers
var zoom = (Vector3.Distance(pos1, pos2) /
Vector3.Distance(pos1b, pos2b));
//edge case (Bad calculation)
if (zoom == 0 || zoom > 10)
return;
//Move cam amount the mid ray. This is where the zoom is applied
// Vector3 pos = Camera.transform.position;
// pos.y = Mathf.Clamp(pos.y, zoomMinY, zoomMaxY);
// Camera.transform.position = Vector3.Lerp(pos1, Camera.transform.position, (1 / zoom));
// Camera.transform.position = pos;
if (Camera.transform.position.y < zoomMinY | Camera.transform.position.y > zoomMaxY)
{
// Camera.transform.position = pos;
Camera.transform.position = Vector3.SmoothDamp(Camera.transform.position, pos, ref velocity, camsummer);
// Camera.transform.position = Vector3.LerpUnclamped(Camera.transform.position, pos, camsummer);
// for (int i = 0; i < 1000; i++)
// {
// }
}
else if (Camera.transform.position.y >= zoomMinY && Camera.transform.position.y <= zoomMaxY)
{
pos = Camera.transform.position;
Camera.transform.position = Vector3.LerpUnclamped(pos1, Camera.transform.position, (1 / zoom));
//This is where the rotation is applied
if (Rotate && pos2b != pos2)
Camera.transform.RotateAround(pos1, Plane.normal,
Vector3.SignedAngle(pos2 - pos1, pos2b - pos1b, Plane.normal) * rotateSpeed * Time.deltaTime);
}
// pos.y = zoomMinY;
}
// if (Camera.transform.position.y > 200)
// {
// zoomMaxY.y = 200;
// Camera.transform.position = zoomMaxY;
// }
// else if (Camera.transform.position.y < 50)
// {
// zoomMinY.y = 50;
// Camera.transform.position = zoomMinY;
// }
// else if (Camera.transform.position.y >= 50 && Camera.transform.position.y <= 200)
// {
// Camera.transform.position = Vector3.LerpUnclamped(pos1, Camera.transform.position, (1 / zoom));
// }
// Vector3 Cam = Mathf.Clamp(Camera.transform.position.y, zoomMinY.y, zoomMaxY.y);
// if (Camera.transform.position.y > zoomMaxY || Camera.transform.position.y < zoomMinY)
// {
// Vector3 camLimit = Camera.transform.position;
// camLimit.y = Mathf.Clamp(Camera.transform.position.y, zoomMinY, zoomMaxY);
// Camera.transform.position = camLimit;
// // Vector3 camLimit = Camera.transform.position;
// // camLimit = (transform.position.);
// // Camera.transform.position = camLimit;
// }
// else if (Camera.transform.position.y >= zoomMinY && Camera.transform.position.y <= zoomMaxY)
// {
// Camera.transform.position = Vector3.LerpUnclamped(pos1, Camera.transform.position, (1 / zoom));
// }
}
protected Vector3 PlanePositionDelta(Touch touch)
{
//not moved
if (touch.phase != TouchPhase.Moved)
return Vector3.zero;
//delta: How far have we moved from A to B by sliding the finger
var rayBefore = Camera.ScreenPointToRay(touch.position - touch.deltaPosition);
var rayNow = Camera.ScreenPointToRay(touch.position);
if (Plane.Raycast(rayBefore, out var enterBefore) && Plane.Raycast(rayNow, out var enterNow))
return rayBefore.GetPoint(enterBefore) - rayNow.GetPoint(enterNow);
//not on plane
return Vector3.zero;
}
protected Vector3 PlanePosition(Vector2 screenPos)
{
//position
var rayNow = Camera.ScreenPointToRay(screenPos);
if (Plane.Raycast(rayNow, out var enterNow))
return rayNow.GetPoint(enterNow);
return Vector3.zero;
}
private void OnDrawGizmos()
{
Gizmos.DrawLine(transform.position, transform.position + transform.up);
}
#endif
}
And to make it easier to see, this is the part I am struggling to make it work.
if (Camera.transform.position.y < zoomMinY | Camera.transform.position.y > zoomMaxY)
{
Camera.transform.position = Vector3.SmoothDamp(Camera.transform.position, pos, ref velocity, camsummer);
}
else if (Camera.transform.position.y >= zoomMinY && Camera.transform.position.y <= zoomMaxY)
{
pos = Camera.transform.position;
Camera.transform.position = Vector3.LerpUnclamped(pos1, Camera.transform.position, (1 / zoom));
//This is where the rotation is applied
if (Rotate && pos2b != pos2)
Camera.transform.RotateAround(pos1, Plane.normal,
Vector3.SignedAngle(pos2 - pos1, pos2b - pos1b, Plane.normal) * rotateSpeed * Time.deltaTime);
}
Does this happen when the camera gets close to an object?
If so change the near clip plane distance on your camera to.near = 0
That should stop it from not showing the gameobject, if ur camera keeps moving it might cause the flickering because it clips in and out of the near clip plane
I am creating a game with Unity and I have a math problem.
I have a sphere with a radius of 10 and center of (0, 0, 0).
I want the camera to move around that sphere, but I can't find anywhere a way to do what I want to.
I move the camera in the X axis and the Y axis (and therefore get a point outside of the sphere) and I want to set it's Z axis so the camera would be back on the sphere, I am using this equation: r^2 = x^2 + y^2 + z^2 => z^2 = r^2 - x^2 - y^2
But it doesn't work… Please help me
EDIT
This is my code (in c#):
private void OnMouseDrag()
{
var newX = mainCameraTransform.position.x + Input.GetAxis("Mouse X");
var newY = mainCameraTransform.position.y + Input.GetAxis("Mouse Y");
var maxDistance = 10.0f;
newX = Mathf.Clamp(newX, -maxDistance * 0.85f, maxDistance * 0.85f);
newY = Mathf.Clamp(newY, 1.0f * 0.85f, maxDistance * 0.85f);
var newZ = Mathf.Sqrt(Mathf.Abs(maxDistance * maxDistance - newX * newX - newY * newY));
mainCameraTransform.position = new Vector3(newX, newY, newZ);
mainCameraTransform.LookAt(Vector3.zero);
}
As you can see I used Clamp to keep the X and Y less then the radius but it didn't help…
This isn't tested, but it should be pretty close
private void OnMouseDrag(){
Vector3 newPos = mainCameraTransform.position;
newPos += mainCameraTransform.up * Input.GetAxis("Mouse Y");
newPos += mainCameraTransform.right * Input.GetAxis("Mouse X");
newPos = newPos.normalized * 10f;
mainCameraTransform.position = newPos;
mainCameraTransform.LookAt(Vector3.zero, mainCameraTransform.up);
}
You have to limit 2D coordinates by circle border
len = Mathf.Sqrt(newX * newX + newY * newY);
//perhaps you have Len or Hypot function in your Math library
if len > maxDistance then
newX = maxDistance * newX / len
newY = maxDistance * newY / len;
Drag and drop this script on the camera to orbit it around a target using the right mouse button
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OrbitAroundObject : MonoBehaviour {
public Transform target;
public float distance = 10.0f;
public float xSpeed = 120.0f;
public float ySpeed = 120.0f;
public float yMinLimit = -20f;
public float yMaxLimit = 80f;
public float distanceMin = .5f;
public float distanceMax = 15f;
public float smoothTime = 2f;
public float zoomSpeed = 1;
float rotationYAxis = 0.0f;
float rotationXAxis = 0.0f;
float velocityX = 0.0f;
float velocityY = 0.0f;
// Use this for initialization
void Start() {
Vector3 angles = transform.eulerAngles;
rotationYAxis = angles.y;
rotationXAxis = angles.x;
// Make the rigid body not change rotation
if (GetComponent<Rigidbody>()) {
GetComponent<Rigidbody>().freezeRotation = true;
}
}
void LateUpdate() {
if (target) {
if (Input.GetMouseButton(1)) {
velocityX += xSpeed * Input.GetAxis("Mouse X") * 0.02f;
velocityY += ySpeed * Input.GetAxis("Mouse Y") * 0.02f;
}
//distance -= (Input.mouseScrollDelta.y*Time.deltaTime);
distance = Mathf.Lerp(distance, distance-(Input.mouseScrollDelta.y*zoomSpeed) , Time.deltaTime * smoothTime);
distance = Mathf.Clamp(distance, distanceMin, distanceMax);
rotationYAxis += velocityX;
rotationXAxis -= velocityY;
rotationXAxis = ClampAngle(rotationXAxis, yMinLimit, yMaxLimit);
//Quaternion fromRotation = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y, 0);
Quaternion toRotation = Quaternion.Euler(rotationXAxis, rotationYAxis, 0);
Quaternion rotation = toRotation;
Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance);
Vector3 position = rotation * negDistance + target.position;
transform.rotation = rotation;
transform.position = position;
velocityX = Mathf.Lerp(velocityX, 0, Time.deltaTime * smoothTime);
velocityY = Mathf.Lerp(velocityY, 0, Time.deltaTime * smoothTime);
}
}
public static float ClampAngle(float angle, float min, float max) {
if (angle < -360F)
angle += 360F;
if (angle > 360F)
angle -= 360F;
return Mathf.Clamp(angle, min, max);
}
}
I am developing endless runner game like subway surfer in Unity.
I want to move my player, smoothly on swipe left or right.
How can do it?
Here is my code:
using UnityEngine;
using System.Collections;
public class SwipeScript3 : MonoBehaviour {
private Touch initialTouch = new Touch();
private float distance = 0;
private bool hasSwiped = false;
//Quaternion targetx = Quaternion.Euler(0, -3f, 0);
//Quaternion targety = Quaternion.Euler(0, 3f, 0);
void FixedUpdate()
{
foreach(Touch t in Input.touches)
{
if (t.phase == TouchPhase.Began)
{
initialTouch = t;
}
else if (t.phase == TouchPhase.Moved && !hasSwiped)
{
float deltaX = initialTouch.position.x - t.position.x;
float deltaY = initialTouch.position.y - t.position.y;
distance = Mathf.Sqrt((deltaX * deltaX) + (deltaY * deltaY));
bool swipedSideways = Mathf.Abs(deltaX) > Mathf.Abs(deltaY);
if (distance > 50f)
{
if (swipedSideways && deltaX > 0) //swiped left
{
//transform.rotation = Quaternion.Slerp (transform.rotation, targetx, Time.deltaTime * 0.8f);
this.transform.Rotate(new Vector3(0, -3f, 0)*Time.deltaTime);
//transform.position = Vector3.Lerp (transform.position,new Vector3(transform.position.x+5f,transform.position.y,transform.position.z),Time.deltaTime*2f );
transform.position = Vector3.Lerp (transform.position, new Vector3 (transform.position.x - 5f, transform.position.y, transform.position.z), Time.deltaTime * 5f);
}
else if (swipedSideways && deltaX <= 0) //swiped right
{
//transform.rotation = Quaternion.Slerp (transform.rotation, targety, Time.deltaTime * 0.8f);
this.transform.Rotate(new Vector3(0, 3f, 0)*Time.deltaTime);
//transform.position = Vector3.Lerp (transform.position, new Vector3 (transform.position.x - 5f, transform.position.y, transform.position.z), Time.deltaTime * f);
transform.position = Vector3.Lerp (transform.position,new Vector3(transform.position.x+5f,transform.position.y,transform.position.z),Time.deltaTime*5f );
}
else if (!swipedSideways && deltaY > 0) //swiped down
{
//this.transform.Rotate(new Vector3(0, 2f, 0));
transform.position = Vector3.Lerp (transform.position,new Vector3(transform.position.x,transform.position.y,transform.position.z-5f),Time.deltaTime*2f );
}
else if (!swipedSideways && deltaY <= 0) //swiped up
{
this.GetComponent<Rigidbody>().velocity = new Vector3(this.GetComponent<Rigidbody>().velocity.x, 0, this.GetComponent<Rigidbody>().velocity.z);
this.GetComponent<Rigidbody>().AddForce(new Vector3(0, 400f, 0));
Debug.Log ("Swiped Up");
}
hasSwiped = true;
}
}
else if (t.phase == TouchPhase.Ended)
{
initialTouch = new Touch();
hasSwiped = false;
}
}
}
}
You could use Vector3.Slerp(Vector3 StartPosition, Vector3 DestinationPosition, float Number)
Number is between 0 and 1 and it indicates where will be the position of your object between StartPosition and DestinationPosition.
Lets say Number = 0.0f;: your object will be at StartPosition.
If Number = 0.5f;: your object will be between StartPosition and DestinationPosition.
You need to increase the Number value from 0 to 1 when swipe action is performed.
The faster you increase the "Number" value, the faster your object will move towards Destination.
You should set you StartPosition once when the swipe action begins, not give your transform.position repeatedly in your Vector3.Slerp() function.
You can find an example here in Unity Docs.
Hope this helps! Cheers!
I found and edited a java script that moves the camera from pointA -> pointB and back when you use the scroll wheel. But when I make it a child of the player, the camera doesn't move with it. Any ideas why?
This script is used by the camera:
var pointB : Vector3;
function Start () {
var pointA = transform.position;
while (true) {
yield MoveObject(transform, pointA, pointB, 3.0);
yield MoveObject(transform, pointB, pointA, 3.0);
}
}
function MoveObject (thisTransform : Transform, startPos : Vector3, endPos : Vector3, t) {
var i = 0.0;
var rate = 0.1;
while (i < 1.0) {
i += Input.GetAxis("Mouse ScrollWheel") * rate;
thisTransform.position = Vector3.Lerp(startPos, endPos, i);
yield;
i = Mathf.Clamp(i, 0.0, 10.0);
}
}
I am working on User Defined Target package of vuforia. Package is working gud but i have problem when i try to drag my 3d model.
That code is working without UserDefinedTarget.
Code is here :
GameObject target = GameObject.FindGameObjectWithTag("Target");
if(Input.touchCount == 1)
{
if (theTouch.phase == TouchPhase.Began)
{
Debug.Log("Touch phase began at: " + theTouch.position);
RaycastHit hit = new RaycastHit();
if (Physics.Raycast(ray, out hit, maxPickingDistance))
{
pickedObject = target.transform;
}
else
{
pickedObject = null;
}
}
else if (theTouch.phase == TouchPhase.Moved)
{
Debug.Log("Touch phase Moved");
if (pickedObject != null)
{
Vector3 translationInCameraRef;
Vector2 screenDelta = theTouch.deltaPosition;
float halfScreenWidth = 0.5f * Screen.width;
float halfScreenHeight = 0.5f * Screen.height;
float dx = screenDelta.x / halfScreenWidth;
float dy = screenDelta.y / halfScreenHeight;
Vector3 objectToCamera =
pickedObject.transform.position - Camera.main.transform.position;
float distance = objectToCamera.magnitude;
float fovRad = Camera.main.fieldOfView * Mathf.Deg2Rad;
float motionScale = distance * Mathf.Tan(fovRad/2);
if(Application.loadedLevelName == "LoadModel")
{
translationInCameraRef =
new Vector3(motionScale * dx, motionScale * dy, 0);
}
else{
translationInCameraRef =
new Vector3(motionScale * dx , motionScale * dy , motionScale * dy);
}
Vector3 translationInWorldRef =
Camera.main.transform.TransformDirection(translationInCameraRef);
pickedObject.position += translationInWorldRef * 5.0f;
}
}
else if (theTouch.phase == TouchPhase.Ended)
{
Debug.Log("Touch phase Ended");
pickedObject = null;
}
}
CAn anyone is having any idea regarding this ? Please help me to solve out this.
Thanks.