I have an 3D model attached to a image target. What I want is to scale the model according to the camera's position, i.e. when I get closer to the model I want it to get larger and when I get far away it should get smaller. I searched the forums and tried two different solutions:
Solution 1:
I created a script and attached to the 3d model:
public class AR_Capsule : MonoBehaviour {
float minimumDistance = 0;
float maximumDistance = 3;
float minimumDistanceScale = 0.3f;
float maximumDistanceScale = 0.1f;
void Update()
{
float distance = (transform.position - Camera.main.transform.position).magnitude;
float norm = (distance - minimumDistance) / (maximumDistance - minimumDistance);
norm = Mathf.Clamp01(norm);
Vector3 minScale = Vector3.one * maximumDistanceScale;
Vector3 maxScale = Vector3.one * minimumDistanceScale;
transform.localScale = Vector3.Lerp(maxScale, minScale, norm);
}
}
Solution 2:
public class AR_Capsule : MonoBehaviour {
public float speed = 10f;
void Update()
{
transform.Translate(0, 0,(-1 * Input.acceleration.z * speed * Time.deltaTime));
}
}
Both solutions work when the image target is visible. But when I lose the target from sight, then the object stays still and camera position is always (0.0, 0.0, 0.0).
Do you have any idea why the object freezes when the target is lost?
I am developing for Epson Moverio bt-300 and working with vuforia eyewear sample app.
Thanks.
I found the issue. The problem is about getting the correct camera position. Since I am using a eyewear Camera.main.transform.position will give always (0,0,0). Instead I used Camera.main.transform.GetChild(1).transform.position which work fine. Below is the working code:
initialDist = Vector3.Distance(transform.position, Camera.main.transform.GetChild(1).transform.position);
distance = Vector3.Distance(lastMarkerpos, Camera.main.transform.GetChild(1).transform.position);
if((transform.localScale.x * (initialDist / distance)) > 0.05 && (transform.localScale.x * (initialDist / distance)) < 2)
{
transform.localScale = new Vector3(transform.localScale.x * (initialDist / distance), transform.localScale.y * (initialDist / distance), transform.localScale.z * (initialDist / distance));
}
Related
Hello i am new in the forum! I hope i am in the right section! Im trying to rotate a camera (that rapresent the player POV) using the mouse delta and im rotating the camera in local coordinates not world coordinates and i want avoid gimbal lock effect. I read somewhere on the internet that for that purpose i have to use quaternions, and i read how to do that. The problem is that axis rotations works well moving in local orientation but one of the axis is losing its local orientation and it rotate following the world coordinates orientation. I will post the code and i hope someone can help me and telling me where im doing things wrong. Thanks!
public class Player : MonoBehaviour {
[Header("Camera")]
[SerializeField] private Camera _camera;
[SerializeField] private Vector2 _xMinMaxRotation = new Vector2(-90, 90);
[SerializeField] private Vector2 _yMinMaxRotation = new Vector2(-90, 90);
[SerializeField] private float _mouseXSensistivity = 1;
[SerializeField] private float _mouseYSensistivity = 1;
[SerializeField] private float _mouseZSensistivity = 1;
[SerializeField] private float _xStartRotation = 0;
[SerializeField] private float _yStartRotation = 0;
private Vector2 _mouseDelta;
private float _rotY, _rotX, _rotZ;
//public GameObject head;
// Start is called before the first frame update
void Start() {
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update() {
_mouseDelta = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
MoveCamera();
}
private void MoveCamera() {
_rotX += _mouseDelta.x * _mouseXSensistivity * Time.deltaTime * 100;
_rotX = Mathf.Clamp(_rotX, _xMinMaxRotation.x, _xMinMaxRotation.y);
_rotY += _mouseDelta.y * _mouseYSensistivity * Time.deltaTime * 100;
_rotY = Mathf.Clamp(_rotY, _yMinMaxRotation.x, _yMinMaxRotation.y);
//Calculation for RotZ
if (Input.GetKey(KeyCode.Q)) {
_rotZ += +_mouseZSensistivity * Time.deltaTime * 50;
if (_rotZ > 25) _rotZ = 25;
}
else {
if (_rotZ > 0) {
_rotZ -= 2 * _mouseZSensistivity * Time.deltaTime * 50;
if (_rotZ < 0) _rotZ = 0;
}
}
if (Input.GetKey(KeyCode.E)) {
_rotZ += -_mouseZSensistivity * Time.deltaTime * 50;
if (_rotZ < -25) _rotZ = -25;
}
else {
if (_rotZ < 0) {
_rotZ -= 2 * -_mouseZSensistivity * Time.deltaTime * 50;
if (_rotZ > 0) _rotZ = 0;
}
}
Quaternion currentRotation = Quaternion.identity;
currentRotation = currentRotation * Quaternion.AngleAxis(_rotX, transform.up);
currentRotation = currentRotation * Quaternion.AngleAxis(-_rotY, transform.right);
currentRotation = currentRotation * Quaternion.AngleAxis(_rotZ, transform.forward);
_camera.transform.localRotation = currentRotation;
//head.transform.position = _camera.transform.position;
//head.transform.rotation = _camera.transform.rotation;
}
The last part with quaternions is where im trying to calculate angles in order to properly rotate in local coordinates.
You don’t need to use quaternions at all.
You can use transform.EulerAngles instead of the transform.rotation or transform.localEulerAngles instead of transform.LocalRotation.
I messed up the capitalization I’m sure.
Say you wanted to rotate the camera 10 degrees along the local x axis. That would look something like
transform.localEulerAngles = transform.localEulerAngles.Add(10,0,0);
That’s it as far as I know. If you wanna read more about this,
transfrom.localEulerAngles
If your question was completely different, let me know and I can change or remove my answer.
I found this code on a web tutorial to make objects float on water in Unity:
RequireComponent (typeof (Rigidbody))]
public class ObjectFloatScript : MonoBehaviour {
public float waterLevel = 0.0f;
public float floatThreshold = 2.0f;
public float waterDensity = 0.125f;
public float downForce = 4.0f;
private float forceFactor;
private Vector3 floatForce;
void FixedUpdate () {
forceFactor = 1.0f - ((transform.position.y - waterLevel) / floatThreshold);
if (forceFactor > 0.0f) {
floatForce = -Physics.gravity * GetComponent<Rigidbody> ().mass * (forceFactor - GetComponent<Rigidbody> ().velocity.y * waterDensity);
GetComponent<Rigidbody> ().AddForceAtPosition (floatForce, transform.position);
}
}
}
What I don't Understand is the relationship between the Rigidbody.velocity.y and the water density ? Can someone help ?
Thanks
It looks like some kind of "belly flop" factor :)
Only having -gravity * mass would result in a force perfectly countering the gravitation force on the object, stopping it instantly.
By scaling this force down by velocity.y * waterDensity, it will reduce this countering force, based on the entry velocity, simulating some kind of "water friction" as the object enters the water.
Cheers!
void HandleMouse()
{
if(Input.GetMouseButton(0))
{
if(isTouching)
{
HandleDragging();
}
}
else
{
isTouching = false;
ResetKnob();
}
}
void HandleTouches()
{
}
protected virtual void HandleDragging()
{
//Get the target position for the knob
Vector2 wantedPosition = Vector2.zero;
RectTransformUtility.ScreenPointToLocalPointInRectangle(bounds, Input.mousePosition, null, out wantedPosition);
knob.anchoredPosition = Vector2.Lerp(knob.anchoredPosition, wantedPosition, Time.deltaTime * dragSpeed);
//Find the normalized Delta for the Knob
float xDelta = knob.anchoredPosition.x / (bounds.rect.width * 0.5f);
float yDelta = knob.anchoredPosition.y / (bounds.rect.height * 0.5f);
finalDelta = new Vector2(xDelta, yDelta);
finalDelta = Vector2.ClampMagnitude(finalDelta, 1f);
}
void ResetKnob()
{
knob.anchoredPosition = Vector2.Lerp(knob.anchoredPosition, Vector2.zero, Time.deltaTime * resetSpeed);
finalDelta = Vector2.zero;
}
I am trying to move a throttle up and down in the 3d space .I am using a 3d throttle object in side the cockpit to move up and down using mouse point i tried for moving the 2d sprite using above code it works fine but not working for moving a 3d throttle object.
spri
Mathf.Lerp(inputvalue, -10f, 10f);
I think your error is you are trying to interpolate your input to 10, when the Lerp function can only interpolate [0,1], Mathf.Lerp
You need to call it as Mathf.Lerp(-10, 10, inputValue);
Once you get the interpolation value just add that to the translation
var value = Mathf.Lerp(-10, 10, inputValue);
transform.position += Vector3.forward * value;
Find out how far your throttle is:
Vector2 throttleDownPosition = Vector2.zero; // Or whatever it is. I can't tell from your code.
Vector2 throttleUpPosition = new Vector2(0f,1f); // Or whatever it is. I can't tell from your code.
Vector2 throttleCurrentPosition = knob.anchoredPosition;
// Calculate ratio between current throttle / full throttle
float throttlePercentage =
Vector2.Distance(throttleCurrentPosition, throttleDownPosition)
/ Vector2.Distance(throttleUpPosition, throttleDownPosition);
Then, using what position and rotation your 3D throttle object should be when throttle is at 0%:
Vector3 startPosition
Quaternion startRotation
as well as the position and rotation your 3D throttle object should be when throttle is at 100%:
Vector3 endPosition
Quaternion endRotation
you can use Vector3.Lerp and Quaternion.Lerp to find the appropriate position and rotation for the current throttle setting:
Vector3 lerpedPosition = Vector3.Lerp(startPosition, endPosition, throttlePercentage);
Quaternion lerpedRotation = Quaternion.Lerp(startRotation, endRotation, throttlePercentage);
throttleObject.transform.position = lerpedPosition;
throttleObject.transform.rotation = lerpedRotation
Im thinking about it two days. I still did not made any progress.
I wonder how to do that objects fly away from mouse click position in 2D view?
I tried like that:
pos = Input.mousePosition;
Vector3 realWorldPos = Camera.main.ScreenToViewportPoint(pos);
print("MOuse pos: " + realWorldPos);
//print(realWorldPos);
Vector3 velo = GetComponent<Rigidbody2D>().velocity;
if (realWorldPos.x < 0.5)
{
velo = new Vector3((realWorldPos.x * speed), velo.y);
}
else if(realWorldPos.x > 0.5)
{
velo = new Vector3((realWorldPos.x * speed) * (-1), velo.y);
}
if (realWorldPos.y < 0.5)
{
velo = new Vector3(velo.x, realWorldPos.y * speed);
}
else if (realWorldPos.y > 0.5)
{
velo = new Vector3(velo.x, (realWorldPos.y * speed) * (-1));
}
GetComponent<Rigidbody2D>().velocity = velo;
But it doesnt work as I want.
Is it possible to do this?
For this to work your Rigidbody2D must have Gravity Scale set to 0.
This is a simple test code that works for me, is placed on a sprite object:
public class PushPlayer : MonoBehaviour
{
public float pushPower = 50.0f;
Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
if(Input.GetMouseButtonDown(0))
{
Vector3 dir = transform.position - Camera.main.ScreenToWorldPoint(Input.mousePosition);
dir = dir.normalized;
rb.AddForce(dir * pushPower, ForceMode2D.Force);
// as alternative:
rb.velocity = dir * pushPower;
}
}
}
You need to adjust the values a bit, also in the regidbody (like drag) to get it the way you want.
Edit:
transform.position - Camera.main.ScreenToWorldPoint(Input.mousePosition): calculate the directional vector from the mouse position to the player position (have a look a vector algebra if you are not familiar with this) which is the direction away from the click (in a straight line).
dir.normalized: this shortens the vector to a length (= magnitude) of 1 (again have a look at vectors) so it really is just a direction. You could omit this and reduce the factor, but doing it this way your factor equals the force you use.
I'm trying to recreate the functionality of the Google Cardboard app’s 'Exhibit' demo. i.e. viewing a single object from all sides - look up and you see under the object, look down and you view it from above, look left or right and you see it from the side, then back.
I've tried a number of things like making the object a child of the camera, and using transform.LookAt(target); to keep the camera focused on the object but it isn't working.
New to Unity5 so any help would be very much appreciated.
UPDATE
Using code from a SmoothMouseLook script (http://pastebin.com/vMFkZJAm) this is the closest I've got so far, but it doesn't really work and feels too 'out of control' (the object keeps spinning rather than smoothly turning for inspection) and much less predictable than the 'Exhibit' demo. My guess is that I'm over complicating things. Anyone have any ideas?...
On the Camera(s) ("Main Camera") attach this to keep focused on the object:
using UnityEngine;
using System.Collections;
public class LookAt : MonoBehaviour {
public Transform target;
void Update () {
transform.LookAt(target);
}
}
On the Object, attach this script:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class SmoothMouseLook : MonoBehaviour
{
/*
This script is used to average the mouse input over x
amount of frames in order to create a smooth mouselook.
*/
//Mouse look sensitivity
public float sensitivityX = 1f;
public float sensitivityY = 1f;
//Default mouse sensitivity
public float defaultSensX = 1f;
public float defaultSensY = 1f;
//Minimum angle you can look up
public float minimumY = -60f;
public float maximumY = 60f;
//Minimum angle you can look up
public float minimumX = -60f;
public float maximumX = 60f;
//Number of frames to be averaged, used for smoothing mouselook
public int frameCounterX = 35;
public int frameCounterY = 35;
//Mouse rotation input
private float rotationX = 0f;
private float rotationY = 0f;
//Used to calculate the rotation of this object
private Quaternion xQuaternion;
private Quaternion yQuaternion;
private Quaternion originalRotation;
//Array of rotations to be averaged
private List<float> rotArrayX = new List<float> ();
private List<float> rotArrayY = new List<float> ();
void Start ()
{
//Lock/Hide cursor
if (GetComponent<Rigidbody>())
GetComponent<Rigidbody>().freezeRotation = true;
originalRotation = transform.localRotation;
}
void FixedUpdate ()
{
//Mouse/Camera Movement Smoothing:
//Average rotationX for smooth mouselook
float rotAverageX = 0f;
//rotationX += Camera.main.transform.eulerAngles.x * sensitivityX;
//rotationX += Cardboard.SDK.HeadRotation.eulerAngles.x * sensitivityX;
rotationX += Cardboard.SDK.HeadPose.Orientation.x * sensitivityX;
rotationX = ClampAngle (rotationX, minimumX, maximumX);
//Add the current rotation to the array, at the last position
rotArrayX.Add (rotationX);
//Reached max number of steps? Remove the oldest rotation from the array
if (rotArrayX.Count >= frameCounterX) {
rotArrayX.RemoveAt (0);
}
//Add all of these rotations together
for (int i_counterX = 0; i_counterX < rotArrayX.Count; i_counterX++) {
//Loop through the array
rotAverageX += rotArrayX[i_counterX];
}
//Now divide by the number of rotations by the number of elements to get the average
rotAverageX /= rotArrayX.Count;
//Average rotationY, same process as above
float rotAverageY = 0;
//rotationY += Camera.main.transform.eulerAngles.y * sensitivityY;
//rotationY += Cardboard.SDK.HeadRotation.eulerAngles.y * sensitivityY;
rotationY += Cardboard.SDK.HeadPose.Orientation.y * sensitivityY;
rotationY = ClampAngle (rotationY, minimumY, maximumY);
rotArrayY.Add (rotationY);
if (rotArrayY.Count >= frameCounterY) {
rotArrayY.RemoveAt (0);
}
for (int i_counterY = 0; i_counterY < rotArrayY.Count; i_counterY++) {
rotAverageY += rotArrayY[i_counterY];
}
rotAverageY /= rotArrayY.Count;
//Apply and rotate this object
xQuaternion = Quaternion.AngleAxis (rotAverageX, Vector3.up);
yQuaternion = Quaternion.AngleAxis (rotAverageY, Vector3.left);
transform.localRotation = originalRotation * xQuaternion * yQuaternion;
}
private float ClampAngle (float angle, float min, float max)
{
if (angle < -360f)
angle += 360f;
if (angle > 360f)
angle -= 360f;
return Mathf.Clamp (angle, min, max);
}
}
For that particular use case, you don't need a script. Assuming you are using the CardboardMain prefab, do this:
Put the object at the origin, and the CardboardMain there too.
In the Cardboard settings, set Neck Model Scale to 0.
Open up CardboardMain and select Main Camera under the Head object.
Set it's Transform Position Z value to a negative value (far enough to see the object).
(You can think of this as the "selfie-stick" camera model.)