I am trying to make it so that the CardboardMain in Unity will slowly drift in the direction that the center point of the VR is pointing. I have the script:
using UnityEngine;
using System.Collections;
public class Move : MonoBehaviour {
public float balloon_speed = 0.0001f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
//float rotLeftRight = Input.GetAxis ("Mouse X");
//transform.Rotate (0, rotLeftRight, 0);
Vector3 direction = new Vector3(0,0,balloon_speed);
direction = transform.rotation * direction;
transform.localPosition += direction;
}
}
If the lines
//float rotLeftRight = Input.GetAxis ("Mouse X");
//transform.Rotate (0, rotLeftRight, 0);
are un-commented, the script works perfectly in Unity. When I load it to an android device, the camera will drift forwards and the direction won't change. I think the reason for this is that the VR coordinates are different from what transform.rotaion will return. Any advice?
I'd try this:
void Update() {
transform.localPosition += balloon_speed * Vector3.forward;
}
I think in your script you were adding a world-coordinate vector (rotation * direction) to the local-coordinate position.
Related
Could anyone tell me how I could make a 3D character move using a mobile joystick? I'm developing for Android on Unity and this one part I'm stuck on, basically I want to be able to move the character with a joystick and then be able to rotate through touching the screen.
For the plugged joystick, it's basically like any PC joystick. So you just have to use the old fashioned Input.GetAxis("Vertical") and Input.GetAxis("Horizontal") method. Be sure to map those in input from all joysticks in your Project preference > Inputs.
Official doc
As for the touch, it also works easily with Input.GetTouch(0).position
Official doc
You may also want to raycast the touch tap in order to get the world-scale position of the position you are touching:
private static Vector3 GetPositionFromScreenPosition(Vector3 screenPosition)
{
Ray ray = Camera.main.ScreenPointToRay(screenPosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
return hit.point;
}
return Vector3.zero;
}
Both works well on the same Update() or FixedUpdate() method.
This is my current code:
using UnityEngine;
using UnityEngine.AI;
public class PlayerMover : MonoBehaviour {
public Joystick joystick;
public float characterSpeed = 175f;
public float turnSpeed = 10f;
void Start() {
joystick = FindObjectOfType<Joystick>();
}
void Update() {
var rigidbody = GetComponent<Rigidbody>();
rigidbody.velocity = new Vector3(joystick.Horizontal * characterSpeed, rigidbody.velocity.y, joystick.Vertical * characterSpeed);
float turn = Input.GetAxis("Horizontal") * turnSpeed;
transform.Rotate(0, turn * turnSpeed * Time.deltaTime, 0);
UpdateAnimator();
}
private void UpdateAnimator() {
Vector3 velocity = GetComponent<Rigidbody>().velocity;
Vector3 localVelocity = transform.InverseTransformDirection(velocity);
float speed = localVelocity.z;
GetComponent<Animator>().SetFloat("movementSpeed", speed);
}
}
I'm trying to rotate the camera around a cube with LookAt() function and using the accelerometer in an Android device. It works well. But I want the rotation to stop at some value in the Y axis. Here is my code so far:
public Transform target; // The object to follow
public float topMargin = 0.2f; // Top rotation margin
// The position of the target
private Vector3 point;
void Start () {
point = target.transform.position;
transform.LookAt (point);
}
void Update () {
// Freeze
if (transform.rotation.y >= topMargin) {
transform.RotateAround (point, new Vector3 (0, 1, 0), 0);
}
// Freeze
else if (transform.rotation.y <= -topMargin) {
transform.RotateAround (point, new Vector3 (0, 1, 0), 0);
} else {
transform.RotateAround (point, new Vector3(0, 1, 0), Input.acceleration.x);
}
}
The problem is that when the camera reaches the top margin, I can't start rotating again in the opposite direction. I've tried with a flag variable but can't get the correct program logic (tried different if/else's). Any suggestion on how to achive this?
You could check for the (intended) rotation direction. If the result would lead to a rotation that is more appropriate (away from the boundary and towards the allowed area) you could "allow" the intended rotation to apply.
I guess using the accelerometer value to check for "intended direction" would be easiest and least error prone. (Rather than checking the rotation itself)
I'm new in Unity and want to create a camera-window like on this website:
http://gamasutra.com/blogs/ItayKeren/20150511/243083/Scroll_Back_The_Theory_and_Practice_of_Cameras_in_SideScrollers.php#h.elfjc4ap4hpe There is a example with Curb Camera Motion. I want to make a camera-window which pushes the camera position as the player hits the window edge.
Any ideas, how to realize this?
I used this code:
using UnityEngine;
using System.Collections;
public class CameraController : MonoBehaviour {
public GameObject player;
public Vector3 min;
public Vector3 max;
private Vector3 offset;
void Start ()
{
offset = transform.position - player.transform.position;
}
void LateUpdate ()
{
Vector3 newPos = player.transform.position + offset;
newPos.x = Mathf.Clamp(x, min.x, max.x);
newPos.y = Mathf.Clamp(x, min.y, max.y);
newPos.z = Mathf.Clamp(x, min.z, max.z);
transform.position = newPos;
}
}
Unfortunately, the camera is moving not correct. Any ideas, how to create a camera-window?
The main issue here is that you need to check your targets position in screen space. Where the object is in screen coordinates. And then move your camera if the target is out of the window in "screen coordinates". The main function to be used here is
Camera.main.WorldToScreenPoint
Following is a basic class that should mimic the effect in the article. This can be improved alot but should be enough to get you started in the right direction.
using UnityEngine;
using System.Collections;
public class CurbCam : MonoBehaviour
{
public Transform targetPosition;
public float camWindowDimension;
Vector2 targetScreenPos;
float deltaX;
float deltaZ;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
//convert target pos to 2D
targetScreenPos = Camera.main.WorldToScreenPoint (targetPosition.position);
if (targetScreenPos.x > (Screen.width/2) + camWindowDimension)
{
deltaX = targetScreenPos.x - ((Screen.width/2) + camWindowDimension);
transform.position = new Vector3(transform.position.x + deltaX, transform.position.y, transform.position.z);
}
if (targetScreenPos.x < (Screen.width/2) - camWindowDimension)
{
deltaX = targetScreenPos.x - ((Screen.width/2) - camWindowDimension);
transform.position = new Vector3(transform.position.x + deltaX, transform.position.y, transform.position.z);
}
if (targetScreenPos.y > (Screen.height/2) + camWindowDimension)
{
deltaZ = targetScreenPos.y - ((Screen.height/2) + camWindowDimension);
transform.position = new Vector3(transform.position.x, transform.position.y, transform.position.z + deltaZ);
}
if (targetScreenPos.y < (Screen.height/2) - camWindowDimension)
{
deltaZ = targetScreenPos.y - ((Screen.height/2) - camWindowDimension);
transform.position = new Vector3(transform.position.x, transform.position.y, transform.position.z + deltaZ);
}
}
}
Clamp The Vector3 before applying it to transform.position
using UnityEngine;
using System.Collections;
public class CameraController : MonoBehaviour {
public GameObject player;
public Vector3 min;
public Vector3 max;
private Vector3 offset;
void Start ()
{
offset = transform.position - player.transform.position;
}
void LateUpdate ()
{
Vector3 newPos = player.transform.position + offset;
newPos.x = Mathf.Clamp(x, min.x, max.x);
newPos.y = Mathf.Clamp(x, min.y, max.y);
newPos.z = Mathf.Clamp(x, min.z, max.z);
transform.position = newPos;
}
}
Maybe is not the best approach but you can put 2 colliders at the edges of your Camera and if the player collide with one of them then the Camera will move in the player direction.
In other way you need to calculate the cámera position and the player position both of them referenced at the same point, the center of your scene for example; lets say that your Camera wide is 10 units and for the player are 2 units and both start position is at (0,0).
So, my Camera edges are at (-5,0) & (5,0); and for my player are at (-1,0) & (1,0). Then I need to calculate at every frame the posiiton of my Camera and the player in order to know when the player reach my left or right corner.
Lets say that the Player moves to right until their position is (4,0) it means that his right corner are at (5,0) so, I need to start moving the Camera if the diference betwen distances are higher than certain value (4 in this case because we are walking forward) and the player keeps moving in that direction.
The only thing to take care of is the distance betwen the center of the cámera and the center of the player. If the diference is > to certain number, or lower if you moves backward, then just move the Camera.
Basically is the distance betwen 2 points.
I want to change the OSMdroid MapView orientation to face the direction which the user is going (calculated with Location.bearingTo between the previous and current user location on each onLocationChanged, and converted into normal degrees instead of the -180/180° East of True North degrees).
This direction is correct, I'm rotating an arrow image towards this direction and it points towards the right direction without fail.
However, when I want to orientate the MapView to these userDirection using the setMapOrientation method (documented here), this isn't working as I want it to be. When I orientate the map towards the user's direction, the arrow image should always be pointing north, right? Because this is want I want to achieve: to make it seem like the arrow is always pointing forward (like a GPS tracker: your location on GPS is always represented by an icon going forward, my arrow is pointing to all kinds of directions because the map orientation is wrong).
I'm guessing the osmdroid.MapView orientation is expecting another sort of degree value, but I've tried converting back to East of True North degrees, didn't work. Or my logic is completely wrong and it is working correctly.
How do set the orientation for the MapView so that it is always facing the user's current direction, so that the arrow is always pointing forward (and not going backwards, right or left, ... )?
I think what you are referring to as is "True North" orientation of Map using the compass True North. For this you need the device Compass or Sensor Listener to get the direction, after getting the heading you need to set it for the MapView. Here is the Snippet which is very helpful.
private void compassHeadingUp() {
if(enableCompassHeadUp){
mSensorManager.registerListener(mySensorEventListener,
SensorManager.SENSOR_ORIENTATION,
SensorManager.SENSOR_DELAY_FASTEST);
} else {
mSensorManager.unregisterListener(mySensorEventListener);
mDirection = 0;
}
}
public SensorListener mySensorEventListener = new SensorListener(){
#Override
public void onAccuracyChanged(int arg0, int arg1) {
}
#Override
public void onSensorChanged(int sensor, float[] values) {
synchronized (this) {
float mHeading = values[0];
if(Math.abs(mDirection-mHeading) > Constance.ROTATION_SENSITIVITY){
mMapView.setMapOrientation(-mHeading);
mDirection = mHeading;
}
Matrix matrix = new Matrix();
mCompassImageView.setScaleType(ScaleType.MATRIX);
matrix.postRotate((float) -mHeading, mCompassImageView.getDrawable().getBounds().width()/2, mCompassImageView.getDrawable().getBounds().height()/2);
//Set your Arrow image view to the matrix
mCompassImageView.setImageMatrix(matrix);
}
}
};
I have solved this issue by inverting degrees like this:
float bearing = location.getBearing();
float t = (360 - bearing);
if (t < 0) {
t += 360;
}
if (t > 360) {
t -= 360;
}
//help smooth everything out
t = (int) t;
t = t / 5;
t = (int) t;
t = t * 5;
mapOSM.setMapOrientation(t);
In AndEngine game, I want to throw a ball physics body. The user sets its angle and force and throws it. Its scenario is same as we can see in Angry Birds. I have calculated both the force and angle but am confused how to apply both simultaneously on ball means the ball should be thrown at calculated angle but with particular force. Can anybody guide me to the right direction?
Here is my code snippet:
#Override
public boolean onAreaTouched(TouchEvent event,ITouchArea pTouchArea, float x, float y) {
// TODO Auto-generated method stub
if(event.isActionDown()) {
......
}
else if(event.isActionMove()) {
......
}
else if(event.isActionCancel() || event.isActionOutside() || event.isActionUp()) {
.....
launchHero(hero, string1.getX1()/PIXEL_TO_METER_RATIO_DEFAULT, string1.getY1()/PIXEL_TO_METER_RATIO_DEFAULT, x/PIXEL_TO_METER_RATIO_DEFAULT, y/PIXEL_TO_METER_RATIO_DEFAULT);
}
public void launchHero(Hero hero, float originX, float originY, float fingerX, float fingerY) {
Vector2 shoot = new Vector2((originX - fingerX), -(originY - fingerY));
shoot = shoot.nor().mul(10);
hero.getBody().setLinearVelocity(shoot);
}
}
return false;
}
I have added negative to (originY - fingerY) because if I don't do this, the ball first goes down then after colliding with base, it goes up.
It's very simple, use Body.setLinearVelocity(Vector2 pVector). Both direction and force are determined by the vector's parameters. Here's a sample code:
Vector2 shoot = new Vector2((originX - fingerX), (originY - fingerY));
body.setLinearVelocity(shoot);
This will shoot the body in the direction made by the finger and place of origin, or, in the case of Angry Birds, the finger and the sling.
If you want to make the force constant and multiply it by some number, you can do this before shooting:
shoot = shoot.nor().mul(multiplier);
You can use
body.applyLinearImpulse(Vector2 impulse, Vector2 point)
I prefer this function on setLinearVelocity because it gives more possibilities. To use this function you need to give the impulse in both coordinates and the body's point where to apply it.