Unity3D: How do I improve my Idle animation (Y-axis) - animation

Okay, I am almost finished with my 2d rpg click to move game. If you look at this video you will be able to see that when I click forward my player, once it gets to it's position, face the wrong direction rather than facing straight towards the players. To make myself more clearer, this is an image of the sprite sheet I am currently using, as you can see it has 8 directions. When you click here (in the game), my player would walk down and face this direction or this direction, rather than facing this direction (the normal/preferred position). This also happens when I click here (in the game) my player would walk up and face this direction or face this direction, rather than facing this direction. How can I make sure that my player face the right direction once it reached it's destination. Again this is only occurring within the Y-axis, so walking along the X-axis is fine.
private Animator anim;
public float speed = 15f;
private Vector3 target;
private bool touched;
private bool playerMovementRef;
void Start () {
target = transform.position;
anim = GetComponent<Animator> ();
}
void Update () {
if (Input.GetMouseButtonDown (0)) {
Vector3 mousePosition = Input.mousePosition;
mousePosition.z = 10; // distance from the camera
target = Camera.main.ScreenToWorldPoint (mousePosition);
target.z = transform.position.z;
var movementDirection = (target - transform.position).normalized;
Vector3 animDirection = Vector3.zero;
if (movementDirection.sqrMagnitude > 0)
{
// Use >= to default to horizontal on both being equal
if (movementDirection.x > movementDirection.y)
animDirection.x = 1;
else
animDirection.y = 1;
anim.SetBool ("walking", true);
anim.SetFloat ("SpeedX", movementDirection.x);
anim.SetFloat ("SpeedY", movementDirection.y);
if (movementDirection.x < 0) {
anim.SetFloat ("LastMoveX", -1f);
} else if (movementDirection.x > 0) {
anim.SetFloat ("LastMoveX", 1f);
} else {
anim.SetFloat ("LastMoveX", 0f);
}
if (movementDirection.y > 0) {
anim.SetFloat ("LastMoveY", 1f);
} else if (movementDirection.y < 0) {
anim.SetFloat ("LastMoveY", -1f);
} else {
anim.SetFloat ("LastMoveY", 0f);
}
}
} else {
if (Mathf.Approximately (transform.position.x, target.x) && Mathf.Approximately (transform.position.y, target.y)) {
touched = false;
anim.SetBool ("walking", false);
} else {
transform.position = Vector3.MoveTowards (transform.position, target, speed * Time.deltaTime);
}
}
}
}

I'm just starting out with Unity, but hope I can help.
From the video you've posted I've noticed that the sprite is only 'wrong' when the oldPosition and newPosition click differs in the X component, e.g. when you would click straight down it would show the desired behavior and sprite.
Have you tried printing out the x and y values that your code is using to calculate which sprite it's setting?
At first I thought that maybe it's because the values you set in the Blend Tree were at -1, 1 etc, and due to normalizing you sometimes wound up with 0.9 for a certain value.
Can you maybe try debugging it with the animator window open, like you did at the end? Writing down the values and comparing them between Desired and Undesired behavior might tell you something more.
Sorry I don't have a concrete solution to your problem, but I hope this helps.
Edit for clarification:
Basically, what I'm recommending is to:
1) Print out the values you are getting when the behavior happens, an example of how to print these things out is by using LogFormat, for example:
Debug.LogFormat("X: {0}, Y: {1}", xPosition, yPosition);
Now, you will get the values printed out when it finishes moving.
2) Write down the values for when the moving finishes with the 'Wrong' sprite, and keep clicking to move until the 'Right' sprite shows up. Write down the values again.
3) Compare each values, and find the differences. Now deduce why the differences are as they are, using the values in conjunction with your blend trees.
4) Once you know why, go back through your code/blend trees and rewrite/fix it to work as you intended it to.

Related

Saving click data to an table (Processing)

I´ve tried looking up the question but sadly I wasnt able to find my an answer to my question in other threads. :(
My problem is the following:
I´ve got my hands on a code which transfers clickdata into a heatmap.
Now what I would need is a way to transfer said clickdata into a table which documents the coordinates.
Here is the (hopefully) relevant part out of the code:
void mouseReleased()
{
if (mouseX >= 0 && mouseX < backgroundImage.width && mouseY >= 0 && mouseY < backgroundImage.height)
{
// blit the clickmapBrush onto the (offscreen) clickmap:
clickmap.blend(clickmapBrush, 0,0,clickmapBrush.width,clickmapBrush.height,mouseX-clickmapBrush.width/2,mouseY-clickmapBrush.height/2,clickmapBrush.width,clickmapBrush.height,BLEND);
// blit the clickmapBrush onto the background image in the upper left corner:
image(clickmapBrush, mouseX-clickmapBrush.width/2, mouseY-clickmapBrush.height/2);
// render the heatmapBrush into the gradientMap:
drawToGradient(mouseX, mouseY);
The code is used for the software "Processing".
I hope my question is specific enough.
Thanks in advance! =)
Here is a sample Processing sketch that will record a list of coordinates for each mouse click:
// We will store a list of coordinates,
// each representing a single mouse click's position
ArrayList<PVector> clickData;
void setup() {
clickData = new ArrayList<PVector>();
// Do any aditional setup you need here
}
void draw() {
// Do any drawing here
}
// Called after each press and release of the mouse
void mouseClicked() {
// Add the mouse's position to our list of mouse click positions
clickData.add(new PVector(mouseX, mouseY));
}
If you want to get the x value of the first recorded mouse click, for example, you can access it through a call to clickData.get(0).x, which first grabs the PVector at position 0 from clickData, then get's the x value associated with that PVector object.
Hope that helps!
You can read about the PVector class here

Why does the position step size change after each render, even though the step value never changes? ( three.js)

I have a very simple cube mesh:
var playerGeo = new THREE.BoxGeometry(5,5,5);
var playerMat = new THREE.MeshLambertMaterial({color: 0xFF1865});
var player = new THREE.Mesh(playerGeo, playerMat);
player.position.x = 0;
player.position.y = -50;
scene.add(player);
and in my render function (which uses reqestAnimationFrame) i have the following code which is meant to move the cube left/right based on wether the user presses the left/right key.
$("body").keydown(function(e) {
if(e.keyCode == 37) {
player.position.x -= 0.01;
}else if(e.keyCode == 39){
player.position.x += 0.01;
}
});
This works. However I noticed slightly weird behaviour, as at first if I press the left key, the cube will go left a tiny amount (what seems to be 0.01), but after quite a few times of pressing the arrow keys the distance in which the cube goes on each press seems to slowly increase. So the first time i press a left/right key, the cube will move left/right about a mm. Within about 10 presses left or right, it moves about a cm each press.
What is going on?
Please ask if you require more info!
Thanks
i am suspecting the position change is ok, but your projection is deformed
query the position after change for example open console and add
console.log("position before"+player.position.x);
if(e.keyCode == 37) {
player.position.x -= 0.01;
}else if(e.keyCode == 39){
player.position.x += 0.01;
}
console.log("position after"+player.position.x);
check if the change is 0.01 as planned
if it is and you are using perspective camera you have to set field of vision correctly to avoid fisheye effect
if neither of these are the the cause you have to provide more information...

How to make a menu with this effect in unity3d?

Sorry, I'll try to explain better.
I want to make a sliding menu where you can select a character. I want the character that is at the center increases in size to know that this is the current character. The effect can be seen in the game of Crossy Road when you want to select a character.
Sorry but I can't upload a imagen because i am new in the forum
I think I might be able to help you without needing too much borrowed code. There are two possibilities here:
You have a perspective camera so the "selected" item can just be closer to the camera.
You have an orthographic camera so you will have to scale things.
For perspective:
List<GameObject> characters; //contains all character.
int selectedIndex = 0; //index to the selected character.
float spacing = 10; //space between chars
void Update()
{
if(Input.GetKeyDown("RightArrow"))
{
selectIndex++;
ApplyChanges();
}
if(Input.GetKeyDown("LeftArrow"))
{
selectIndex--;
ApplyChanges();
}
}
void ApllyChanges()
{
// Make sure the selected index is within range and then space the characters.
selectedIndex = selectedIndex % character.Count();
SpaceCharacters();
}
void SpaceCharacters()
{
for(int i = 0; i < characters.Count(); ++i)
{
// characters on the left will have a negative spacing and so will be placed to the left and vice versa for characters on the right.
int offset = i - selectedIndex;
characters[i].transform.position = new Vector3(offset * spacing, 0, 0);
}
// Move the selected character closer.
characters[selectedIndex].transform.position = new Vector3(0,0,spacing);
}
For orthographic camera you will need to set the select characters transform.scale to a larger vector.
This won't animate anything or look cool. This code will just snap your characters into position.
The solution I adopted was to attach objects to the transparent buttons in a scrool rect, so as to manage 3d objects with the convenient of scrool rect interface.
Here you can find the official documentation for use scrool rect: http://docs.unity3d.com/Manual/script-ScrollRect.html
Maybe my assets can serve you ;)
https://www.assetstore.unity3d.com/en/#!/content/60233

affectedbygravity in SceneKit?

I want to make a floating ball.
In spritekit I do physicsbody.affectedbygravity=NO;
But what have I do in scenekit?
I tried to set mass to zero, but dynamicbody turns to static: it not moved by gravity, nor by collision. My code is
// add ball
SCNNode *ball = [SCNNode node];
ball.geometry = [SCNSphere sphereWithRadius:5];
ball.geometry.firstMaterial.locksAmbientWithDiffuse = YES;
ball.geometry.firstMaterial.diffuse.contents = #"ball.jpg";
ball.geometry.firstMaterial.diffuse.contentsTransform = SCNMatrix4MakeScale(2, 1, 1);
ball.geometry.firstMaterial.diffuse.wrapS = SCNWrapModeMirror;
ball.physicsBody = [SCNPhysicsBody dynamicBody];
ball.physicsBody.restitution = 0.9;
//ball.physicsBody.mass=0; //here makes a ball statical and not moving
ball.physicsBody.allowsResting = YES;
[[scene rootNode] addChildNode:ball];
UPD this not helps too - ball falls slowly.
- (void)renderer:(id<SCNSceneRenderer>)aRenderer didSimulatePhysicsAtTime:(NSTimeInterval)time{
[ball.physicsBody applyForce:SCNVector3Make(0, 9.8, 0) atPosition:SCNVector3Make(0,0,0) impulse:NO]; //this
ball.physicsBody.velocity=SCNVector3Make(0,0,0); //or this
}
You can turn off gravity by setting scene.physicsWorld.gravity to zero.
However If you want some objects to be affected and some not you need to add a [SCNPhysicsField linearGravityField] and configure the categoryBitMask to make it affect the nodes you want.
I found partial solution and some fun bug.
This makes ball stay unmovable until collision and "float" after that
// .... the same code above in creation
ball.physicsBody.mass=1;
[[scene rootNode] addChildNode:ball];
ball.physicsBody.mass=0; //important right after creating!!! or it become bodyless after changing mass to 1
and release it if contact. If you apply up force equal to gravity, it will be floating, slowly falling down. Speed of falling may be damped, of cause.
// physics contact delegate
- (void)physicsWorld:(SCNPhysicsWorld *)world didBeginContact:(SCNPhysicsContact *)contact{
if (contact.nodeA.physicsBody.type == SCNPhysicsBodyTypeDynamic && contact.nodeA.physicsBody.mass==0)
contact.nodeA.physicsBody.mass=1;
else
if (contact.nodeB.physicsBody.type == SCNPhysicsBodyTypeDynamic && contact.nodeB.physicsBody.mass==0)
contact.nodeB.physicsBody.mass=1;
}

How do I correctly get control bound coordinates relitive to the control for mouse comparison?

I am presently learning C# and have chosen as a project to write a simple colour picker control ; however things have changed substantially since I last looked at writing code and I have struck this problem.
I am using the Mousedown event in my control to get the mouse coordinates as a Point - this is working fine and returns exactly what I would expect - the mouse coordinates relative to my control; however when I try and do a check against the control location I am returned a value as a Point showing the position of my control relative to the form which in certain cases the mouse coordinates will be outside the bounds of because their values will be less than the relative start position of the control I.E I click at pixel 1,1 in the control - the mouse position is 1,1 but because the control is located at 9,9 relative to the form the location of the mouse is less than the bounds of the control - I have absolutely no idea how to fix this, I have been attempting to sort it out with PointToClient and PointToScreen to no avail as they seem to come up with outlandish values can someone please help me out it's driving me insane.
I've managed to sort this out myself so thought I'd post the answer and it can hopefully help someone else. I was having problems getting Point values that were relative to the same pixel origin : this sorted it.
private void ColourPicker_MouseDown(object sender, MouseEventArgs e)
{ // Probably being paranoid but I am worried about scaling issues, this.Location
// would return the same result as this mess but may not handle
// scaling <I haven't checked>
Point ControlCoord = this.PointToClient(this.PointToScreen(this.Location));
int ControlXStartPosition = ControlCoord.X;
int ControlYStartPosition = ControlCoord.Y;
int ControlXCalculatedWidth = ((RectangleColumnsCount + 1) * WidthPerBlock ) + ControlXStartPosition;
int ControlYCalculatedHeight = ((RectangleRowsCount + 1) * HeightPerBlock) + ControlYStartPosition;
// Ensure that the mouse coordinates are comparible to the control coordinates for boundry checks.
Point ControlRelitiveMouseCoord = this.ParentForm.PointToClient(this.PointToScreen(e.Location));
int ControlRelitiveMouseXcoord = ControlRelitiveMouseCoord.X;
int ControlRelitiveMouseYcoord = ControlRelitiveMouseCoord.Y;
// Zero Relitive coordinates are used for caluculating the selected block location
int ZeroRelitiveXMouseCoord = e.X;
int ZeroRelitiveYMouseCoord = e.Y;
// Ensure we are in the CALCULATED boundries of the control as the control maybe bigger than the painted area on
// the design time form and we don't want to use unpaited area in our calculations.
if((ControlRelitiveMouseXcoord > ControlXStartPosition) && (ControlRelitiveMouseXcoord < ControlXCalculatedWidth))
{
if((ControlRelitiveMouseYcoord > ControlYStartPosition) && (ControlRelitiveMouseYcoord < ControlYCalculatedHeight))
{
SetEvaluatedColourFromPosition(ZeroRelitiveXMouseCoord, ZeroRelitiveYMouseCoord);
}
}
}

Resources