I would like to rotate a sprite on the scene by pressing the left or right arrows keys (think of the spaceship in Asteroids).
I have placed the sprite in question on the scene and created a script, but am not really certain of where to go from there.
My current script looks like this:
using UnityEngine;
using System.Collections;
public class RotateLeftRight : MonoBehaviour {
public float speed = 1.0f;
public string axisName = "Horizontal";
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if(Input.GetKeyDown(KeyCode.LeftArrow)) {
// left
transform.Rotate(-1.0f, 0.0f, 0.0f); // does nothing, just a bad guess
}
if(Input.GetKeyDown(KeyCode.RightArrow)) {
// right
transform.Rotate(1.0f, 0.0f, 0.0f); // does nothing, just a bad guess
}
}
}
I just coded the above without any knowledge of what would happen (and, hardly surprising, nothing appears to happen at all).
Any advice on how to rotate the sprite and control the speed of the rotation would be greatly appreciated.
I'm not able to try it with Unity right now, but my guess is that it is either rotating just 1º, so you are not able to notice it, or rotating 360º, and so it really stays the same.
Try to break down your problem:
Instead of transform.Rotate try transform.Translate(20f, 20f, 20f) just to make sure it is recognizing the input;
Use a different value instead of 1.0f, such as 0.1f and 30.0f (I think 30.0f would be 30º, but I'm not sure);
Try changing the rotation on the other axes y and z instead of x;
Use the alternative definition Rotate(Vector3 axis, float angle).
Hope it helps!
#Sailing Judo, here's the best answer if you want to rotate it like a wheel. Try observe again to your code and instead of putting/changing the X-axis as parameter, put your value at the Z-axis instead. Changing x or y-axis in a circular rotation ended up like flipping coins. Observe and try again.
if(Input.GetKey(KeyCode.LeftArrow)) {
// Clockwise
transform.Rotate(0, 0, -3.0f); // --> Instead of "transform.Rotate(-1.0f, 0.0f, 0.0f);"
}
if(Input.GetKey(KeyCode.RightArrow)) {
// Counter-clockwise
transform.Rotate(0, 0, 3.0f); // --> Instead of transform.Rotate(1.0f, 0.0f, 0.0f);
}
Related
I have a question regarding rendering with box2d and libgdx.
As you can see in the screenshot below I have a problem when changing the window resolution.
Box2d gets scaled over the entire screen although the viewport is only using a small portion of it. Also the lights get scaled and do not match the real position anymore (but I think this is related to the same issue).
My idea is that I somehow need to adjust the matrix (b2dCombinedMatrix) for box2d before rendering but I have no idea how.
Personally I think that I need to tell it that it should use the same "render boundaries" as the viewport but I cannot figure out how to do that.
Here is the render method (the issue is after the draw lights comments part):
public void render(final float alpha) {
viewport.apply();
spriteBatch.begin();
AnimatedTiledMapTile.updateAnimationBaseTime();
if (mapRenderer.getMap() != null) {
mapRenderer.setView(gameCamera);
for (TiledMapTileLayer layer : layersToRender) {
mapRenderer.renderTileLayer(layer);
}
}
// render game objects first because they are in the same texture atlas as the map so we avoid a texture binding --> better performance
for (final Entity entity : gameObjectsForRender) {
renderEntity(entity, alpha);
}
for (final Entity entity : charactersForRender) {
renderEntity(entity, alpha);
}
spriteBatch.end();
// draw lights
b2dCombinedMatrix.set(spriteBatch.getProjectionMatrix());
b2dCombinedMatrix.translate(0, RENDER_OFFSET_Y, 0);
rayHandler.setCombinedMatrix(b2dCombinedMatrix, gameCamera.position.x, gameCamera.position.y, gameCamera.viewportWidth, gameCamera.viewportHeight);
rayHandler.updateAndRender();
if (DEBUG) {
b2dRenderer.render(world, b2dCombinedMatrix);
Gdx.app.debug(TAG, "Last number of render calls: " + spriteBatch.renderCalls);
}
}
And this is the resize method which moves the viewport up by 4 world units:
public void resize(final int width, final int height) {
viewport.update(width, height, false);
// offset viewport by y-axis (get distance from viewport to viewport with offset)
renderOffsetVector.set(gameCamera.position.x - gameCamera.viewportWidth * 0.5f, RENDER_OFFSET_Y + gameCamera.position.y - gameCamera.viewportHeight * 0.5f, 0);
gameCamera.project(renderOffsetVector, viewport.getScreenX(), viewport.getScreenY(), viewport.getScreenWidth(), viewport.getScreenHeight());
viewport.setScreenY((int) renderOffsetVector.y);
}
After hours of fiddling around with the matrix I finally got it to work but there is actually a very easy solution to my problem :D
Basically the render method of the rayhandler was messing up my matrix calculations all the time and the reason is that I did not tell it to use a custom viewport.
So adjusting the resize method to this
public void resize(final int width, final int height) {
viewport.update(width, height, false);
// offset viewport by y-axis (get distance from viewport to viewport with offset)
renderOffsetVector.set(gameCamera.position.x - gameCamera.viewportWidth * 0.5f, RENDER_OFFSET_Y + gameCamera.position.y - gameCamera.viewportHeight * 0.5f, 0);
gameCamera.project(renderOffsetVector, viewport.getScreenX(), viewport.getScreenY(), viewport.getScreenWidth(), viewport.getScreenHeight());
viewport.setScreenY((int) renderOffsetVector.y);
rayHandler.useCustomViewport(viewport.getScreenX(), viewport.getScreenY(), viewport.getScreenWidth(), viewport.getScreenHeight());
}
and simplifying the render method to
// draw lights
rayHandler.setCombinedMatrix(gameCamera);
rayHandler.updateAndRender();
if (DEBUG) {
b2dRenderer.render(world, b2dCombinedMatrix);
Gdx.app.debug(TAG, "Last number of render calls: " + spriteBatch.renderCalls);
}
solved my problem.
Maybe I am stupid but I did not find useCustomViewport method in any of the documentations.
Anyway , solved!
I have used Animation() method to make my view with the animation of scaling and Rotation. With the Rotation based on the Y axis, the default height and width of my view has been changed. It looks like the parallelogram.
rotation of rectangle along y-axis transformed to a parallelogram.
myview.Animate().RotationY(rotationangle)
.X(xposition)
.SetDuration(mduration)
.WithLayer()
.SetInterpolator(interpolate).Start();
My requirement:
I just want the rotation of my view no need to change its projection. How to restrict the rotation of rectangle along y-axis transformed to a parallelogram.
For more reference, please check the attached sample
now view be like,
Image
Please share your idea.
Thanks in Advance.
Note: while using PivotX and PivotY, there is no parallelogram shape. But I don't know the exact usage of that.
Regards,
Hemalatha Marikumar
is that not what are you looking for ?
it may work if you put this code in your current activity
Android: Temporarily disable orientation changes in an Activity
Do you want to create a 2D rotation?
You could try to use ScaleAnimation to rotate the view. If you want to rotate 360 degrees, you could use AnimationListener.
For example:
Button myview = (Button)FindViewById(Resource.Id.button2);
ScaleAnimation scaleAnimation = new ScaleAnimation(1, 0, 1, 1,
Android.Views.Animations.Dimension.RelativeToParent, 0.5f, Android.Views.Animations.Dimension.RelativeToParent, 0.5f);
ScaleAnimation scaleAnimation2 = new ScaleAnimation(0, 1, 1, 1,
Android.Views.Animations.Dimension.RelativeToParent, 0.5f, Android.Views.Animations.Dimension.RelativeToParent, 0.5f);
scaleAnimation.Duration = 4000;
scaleAnimation.SetAnimationListener(new AnimationListener(myview, scaleAnimation2));
scaleAnimation2.Duration = 4000;
myview.StartAnimation(scaleAnimation);
The Listener:
public class AnimationListener :Java.Lang.Object, IAnimationListener
{
View view;
Animation animation2;
public AnimationListener(View view, Animation animation)
{
this.view = view;
this.animation2 = animation;
}
public void OnAnimationEnd(Animation animation)
{
view.StartAnimation(animation2);
}
public void OnAnimationRepeat(Animation animation)
{
}
public void OnAnimationStart(Animation animation)
{
}
}
I am trying to rotate a vector I have created in illustrator using processing. I would like it to rotate this vector from it's center so it appears to be spinning as oppose to moving around an invisible point. Below is my attempt:
PShape WOE;
void setup(){
WOE = loadShape("WOE.svg");
size (500, 500);
smooth();
}
void draw(){
background(20);
shape(WOE, width/2, height/2, WOE.width, WOE.height); //draw shape in "center" of canvas (250, 250)
translate(-WOE.width/2, -WOE.height/2); //move shape so that center of shape is aligned with 250, 250
WOE.rotate(0.01);
}
From a strictly logical point of view this should work, however this results in the vector rotating around the center of the canvas, but approximately 100px away. I have tried using shapeMode(CENTER); but this unfortunately causes no improvement. Hope someone can help, thanks!
For Reference
Here is WOE.svg: https://www.dropbox.com/s/jp02yyfcrrnep93/WOE.svg?dl=0
I think part of your problem is that you're mixing rotating the shape and translating the entire sketch. I would try to stick with one or the other: either translate and rotate the entire sketch, or only translate and rotate the shape.
That being said, I'm not surprised this gave you trouble.
I would expect this to work:
PShape WOE;
void setup() {
size (500, 500);
WOE = loadShape("WOE.svg");
WOE.translate(-WOE.width/2, -WOE.height/2);
}
void draw() {
background(20);
WOE.rotate(.01);
shape(WOE, width/2, height/2);
}
However, this exhibits the same off-center behavior you're noticing. But if I switch to the P2D renderer, it works fine!
size (500, 500, P2D);
Now the shape is centered in the window and rotates around the shape's center. The difference between renderers seems buggy, but I can't find an open bug on GitHub. Edit: I found this SO question, which lead to this GitHub issue.
In any case, it might be easier to rotate the entire sketch instead of the shape:
PShape WOE;
float rotation = 0;
void setup() {
size (500, 500);
WOE = loadShape("WOE.svg");
shapeMode(CENTER);
}
void draw() {
background(20);
translate(width/2, height/2);
rotate(rotation);
shape(WOE);
rotation += .01;
}
This code works by translating the entire sketch to the center of the window, then rotating the entire sketch, then drawing the shape. Think of this like moving the camera instead of moving the shape. If you have other stuff to draw, then you can use the pushMatrix() and popMatrix() functions to isolate the transformation. This works the same in the default renderer and the P2D renderer.
I'm having alot of trouble with the Google IO codelab for Tango https://io2015codelabs.appspot.com/codelabs/project-tango#1
After I finished it, it runs but it only turns, it doesnt move forward and backwars like the other tango apps in the play store.
I started on this yesterday but even after two days of debugging, I cannot get it to work right. Today I got so frustrated that I deleted everything and started over from scratch and it is still broken. I can get the permissions so I think tango is up and running, but not moving. I have enabled motion tracking and disabled/removed the scripts and code as specified in the tutorial. My PoseController looks like this:
using UnityEngine;
using System.Collections;
using Tango;
using System;
public class PoseController : MonoBehaviour , ITangoPose {
private TangoApplication m_tangoApplication; // Instance for Tango Client
private Vector3 m_tangoPosition; // Position from Pose Callback
private Quaternion m_tangoRotation; // Rotation from Pose Callback
private Vector3 m_startPosition; // Start Position of the camera
private Vector3 m_lastPosition; // last position returned in Unity coordinates.
// Controls movement scale, use 1.0f to be metric accurate
// For the codelab, we adjust the scale so movement results in larger movements in the
// virtual world.
private float m_movementScale = 10.0f;
// Use this for initialization
void Start ()
{
// Initialize some variables
m_tangoRotation = Quaternion.identity;
m_tangoPosition = Vector3.zero;
m_lastPosition = Vector3.zero;
m_startPosition = transform.position;
m_tangoApplication = FindObjectOfType<TangoApplication>();
if(m_tangoApplication != null)
{
RequestPermissions();
}
else
{
Debug.Log("No Tango Manager found in scene.");
}
}
// Permissions callback
private void PermissionsCallback(bool success)
{
if(success)
{
m_tangoApplication.InitApplication(); // Initialize Tango Client
m_tangoApplication.InitProviders(string.Empty); // Initialize listeners
m_tangoApplication.ConnectToService(); // Connect to Tango Service
}
else
{
AndroidHelper.ShowAndroidToastMessage("Motion Tracking Permissions Needed", true);
}
}
private void RequestPermissions()
{
// Request Tango permissions
m_tangoApplication.RegisterPermissionsCallback(PermissionsCallback);
m_tangoApplication.RequestNecessaryPermissionsAndConnect();
m_tangoApplication.Register(this);
}
// Pose callbacks from Project Tango
public void OnTangoPoseAvailable(Tango.TangoPoseData pose)
{
// Do nothing if we don't get a pose
if (pose == null) {
Debug.Log("TangoPoseData is null.");
return;
}
// The callback pose is for device with respect to start of service pose.
if (pose.framePair.baseFrame == TangoEnums.TangoCoordinateFrameType.TANGO_COORDINATE_FRAME_START_OF_SERVICE &&
pose.framePair.targetFrame == TangoEnums.TangoCoordinateFrameType.TANGO_COORDINATE_FRAME_DEVICE)
{
if (pose.status_code == TangoEnums.TangoPoseStatusType.TANGO_POSE_VALID)
{
// Cache the position and rotation to be set in the update function.
m_tangoPosition = new Vector3((float)pose.translation [0],
(float)pose.translation [1],
(float)pose.translation [2]);
m_tangoRotation = new Quaternion((float)pose.orientation [0],
(float)pose.orientation [1],
(float)pose.orientation [2],
(float)pose.orientation [3]);
}
else // if the current pose is not valid we set the pose to identity
{
m_tangoPosition = Vector3.zero;
m_tangoRotation = Quaternion.identity;
}
}
}
/// <summary>
/// Transforms the Tango pose which is in Start of Service to Device frame to Unity coordinate system.
/// </summary>
/// <returns>The Tango Pose in unity coordinate system.</returns>
/// <param name="translation">Translation.</param>
/// <param name="rotation">Rotation.</param>
/// <param name="scale">Scale.</param>
Matrix4x4 TransformTangoPoseToUnityCoordinateSystem(Vector3 translation,
Quaternion rotation, Vector3 scale)
{
// Matrix for Tango coordinate frame to Unity coordinate frame conversion.
// Start of service frame with respect to Unity world frame.
Matrix4x4 m_uwTss;
// Unity camera frame with respect to device frame.
Matrix4x4 m_dTuc;
m_uwTss = new Matrix4x4();
m_uwTss.SetColumn (0, new Vector4 (1.0f, 0.0f, 0.0f, 0.0f));
m_uwTss.SetColumn (1, new Vector4 (0.0f, 0.0f, 1.0f, 0.0f));
m_uwTss.SetColumn (2, new Vector4 (0.0f, 1.0f, 0.0f, 0.0f));
m_uwTss.SetColumn (3, new Vector4 (0.0f, 0.0f, 0.0f, 1.0f));
m_dTuc = new Matrix4x4();
m_dTuc.SetColumn (0, new Vector4 (1.0f, 0.0f, 0.0f, 0.0f));
m_dTuc.SetColumn (1, new Vector4 (0.0f, 1.0f, 0.0f, 0.0f));
m_dTuc.SetColumn (2, new Vector4 (0.0f, 0.0f, -1.0f, 0.0f));
m_dTuc.SetColumn (3, new Vector4 (0.0f, 0.0f, 0.0f, 1.0f));
Matrix4x4 ssTd = Matrix4x4.TRS(translation, rotation, scale);
return m_uwTss * ssTd * m_dTuc;
}
// FixedUpdate is called at a fixed rate
void FixedUpdate()
{
// Convert position and rotation from Tango's coordinate system to Unity's.
Matrix4x4 uwTuc = TransformTangoPoseToUnityCoordinateSystem(m_tangoPosition,
m_tangoRotation, Vector3.one);
Vector3 newPosition = (uwTuc.GetColumn(3))* m_movementScale;
Quaternion newRotation = Quaternion.LookRotation(uwTuc.GetColumn(2),
uwTuc.GetColumn(1));
// Calculate the difference in the poses received. This allows us
// to recover when we hit something in the virtual world.
Vector3 delta = newPosition - m_lastPosition;
m_lastPosition = newPosition;
Vector3 destination = rigidbody.position + delta;
Vector3 vectorToTargetPosition = destination - transform.position;
// If there is motion, move the player around the scene.
if(vectorToTargetPosition.magnitude > 0.1f)
{
vectorToTargetPosition.Normalize();
// Set the movement vector based on the axis input.
Vector3 movement = vectorToTargetPosition;
// Normalise the movement vector and make it proportional to the speed per second.
movement = movement.normalized * 5f * Time.deltaTime;
// Move the player to it's current position plus the movement.
rigidbody.MovePosition (transform.position + movement);
}
else {
rigidbody.velocity = Vector3.zero;
}
// always rotate, even if we don't move.
rigidbody.MoveRotation (newRotation);
// finally, let the game manager know the position of the player.
GameManager.Instance.PlayerPosition = transform.position;
}
}
That was just a copy and paste of what was in the codelab, so at this point there is none of my own code and still I cannot run this correctly. What am I doing wrong????
I've done some android development before tango but I'm fairly new to unity. However, I've double and triple checked everything and also my device says everything is up to date.
Thanks in advance!
It looks like the codelab has been updated and the last line in FixedUpdate was commented out "//GameManager.Instance.PlayerPosition = transform.position;".
https://io2015codelabs.appspot.com/codelabs/project-tango#7
Hope that helps.
I am working on an app in which images are flying on the Screen.
I need to implement:
Hold onto any of the flying images on Tap
Drag the image to certain position of the user's choice by letting the user hold it.
Here is another easy way to do dragging.
Just draw your image (Texture2d) with respect to a Rectangle instead of Vector2.
Your image variables should look like this
Texture2d image;
Rectangle imageRect;
Draw your image with respect to "imageRect" in Draw() method.
spriteBatch.Draw(image,imageRect,Color.White);
Now in Update() method handle your image with single touch input.
//Move your image with your logic
TouchCollection touchLocations = TouchPanel.GetState();
foreach(TouchLocation touchLocation in touchLocations)
{
Rectangle touchRect = new Rectangle
(touchLocation.Position.X,touchLocation.Position.Y,10,10);
if(touchLocation.State == TouchLocationState.Moved
&& imageRect.Intersects(touchRect))
{
imageRect.X = touchRect.X;
imageRect.Y = touchRect.Y;
}
//you can bring more beauty by bringing centre point
//of imageRect instead of initial point by adding width
//and height to X and Y respectively and divide it by 2
There's a drag-and-drag example in XNA here: http://geekswithblogs.net/mikebmcl/archive/2011/03/27/drag-and-drop-in-a-windows-xna-game.aspx
When you load your image in, you'll need a BoundingBox or Rectangle Object to control where it is.
So, in the XNA app on your phone, you should have a couple of objects declared for your texture.
Texture2D texture;
BoundingBox bBox;
Vector2 position;
bool selected;
Then after you load your image content, keep your bounding box updated with the position of your image.
bBox.Min = new Vector3(position, 1.0f);
bBox.Max = new Vector3(position.X + texture.Width, position.Y + texture.Height, 0f);
Then also in your update method, you should have a touch collection initialized to handle input from the screen, get the positions of the touch collection, loop through them and see if they intersect your boundingbox.
foreach (Vector2 pos in touchPositions)
{
BoundingBox bb = new BoundingBox();
bb.Min = new Vector3(pos, 1.0f);
bb.Max = new Vector3(pos, 0f);
if (bb.Intersects(bBox)
{
if (selected)
{
//do something
}
else
{
selected = true;
}
}
}
From there, you have whether your object is selected or not. Then just use the gestures events to determine what you want to do with your texture object.