#pragma strict
var anim : Animator;
function Start () {
anim = GetComponent("Animator");
}
function Update () {
if (Input.GetButtonDown("Fire1"))
{
anim.SetFloat("hit",1);
}
}
I have set 'hit' float parameter with 'attack' state, if value of 'hit' > 0.1 , then make transition to 'attack' state from 'Idle state'.
Now problem is, when i click mouse left button, the transition goes from Idle to 'attack' and model perform the desired task, then transition goes from 'attack to Idle' and then again transition goes 'Idle to attack' and goes in loop.
I have set LoopTime, Loop poseto unchecked in animationClip, but still the same is happening.
I understand, the above goes in loop, because the 'hit' parameter never becomes < 0.1 so everytime the condition gets true and transition happens to attack state.
If i add the below line to the above Update() function , then transition never happens.
anim.SetFloat("hit",0);
I dont know where is the problem, what should i do ??, i want when i click mouse left button, then model should hit once and then goes back to Idle state, then again if i click mouse left click, then only it should it..
Any help ?? Please
Thanks in advance
you can use trigger for things that happens once and then they should get back to the state they came from like hitting or jumping or etc
anim.SetTrigger("hit");
Single attack animation control parameter should be a Trigger instead of float. This way animator will stay in idle.
If you want to use float than after finishing the animation you have to set the float value to 0. This way parameter doesn't stay greater than 0.1 which is must for float to stay at default animation.
Related
The character starts with an 'idle' animation. When direction.magnitude is greater than 0 it goes to 'walk' animation. When I press the shift key it goes to the 'sprint' animation. My problem is that when it has to go from 'walk' to 'sprint' it doesn't do it directly walk->sprint only walk->idle->sprint. This causes an unsightly effect when the animation transitions.
How to smoothly transition between animations so that it doesn't automatically go back to 'idle'?
enter image description here
My animator settings:
Idle to Walk (walk is true)
Walk to Idle (walk is false)
Walk to Sprint (sprint is true)
Sprint to Walk (sprint is false)
Idle to Sprint (sprint is true)
Sprint to Idle (sprint is false)
When only one state should be at a time regarding something (in this case the movement animation), I like to use only one variable for it to avoid situations where for example walk and run is both true, or walk false and run is true, etc.
Make an int "State" parameter in the animator, and create the transitions like
idle -> walk if State == 1
idle -> run if State == 2
walk -> idle if State == 0
walk -> run if State == 2
run -> idle if State == 0
run -> walk if State == 1
On the code side, create an enum for better readability:
private enum AnimState
{
Idle,
Walk,
Run
}
And you just need to set the state in the script, something like this (half-pseudo-code):
if (move)
{
if (shift_down) _animator.SetInt("State", (int)AnimState.Run);
else _animator.SetInt("State", (int)AnimState.Walk);
}
else _animator.SetInt("State", (int)AnimState.Idle);
I have a little question about framer. Currently I have a little privat project in which I need to run different actions when the mouse is pressed or not.
To make it easier to talk about, I set up a simple scene with a rectangle. Now I want that the rectangle rotates to the right when the mouse is pressed and rotates to the left when the mouse isn't pressed.
layer = new Layer
x: Align.center
y: Align.center
layer.onMouseDown ->
layer.rotation += 1
layer.onMouseUp ->
layer.rotation -= 1
The problem is that the code only checks once if the mouse is pressed or not. I don't know how I let the program check continuously if the button is pressed or not.
Could anyone help me please?
If you want something to happen repeatedly without events being fired (because mouseUp and mouseDown only get fired once per mouseclick), you can use intervals. Here's an example that does what you describe:
intervalDown = null
intervalUp = null
layer.onMouseDown ->
window.clearInterval(intervalUp)
intervalDown = Utils.interval 0.1, ->
layer.rotation += 1
layer.onMouseUp ->
window.clearInterval(intervalDown)
intervalUp = Utils.interval 0.1, ->
layer.rotation -= 1
You need to create an interval on every event and clear it again using window.clearInterval when the other event fires.
Here's the full example: https://framer.cloud/SEYHy
Running Xcode 8.2 on a Swift Playground. It's also making Xcode not respond. This is the error I'm getting.
Context leak detected, msgtracer returned -1
I've traced the problem to these lines of code
while (true){
let rotate = SKAction.rotate(toAngle: angle - CGFloat(M_PI_2), duration: 1)
crank.run(rotate)
}
When I comment out the while loop and leave just the inside it works fine.
The while (true){ part will make that loop execute forever and your code probably will not proceed beyond that point. If you want an action to repeat forever there is an SKAction method for that - take a look at repeat.
If you remove the while (true){ condition and instead use a repeat action, I believe your code should run fine.
#Fahim is 100% correct, by the code posted you are stuck in an endless loop. So the question for you is how to get out of it?
The question for you is - how to make this loop do what you need. I'll guess that you want to change the condition to something like while (someVar == true) and put in a condition inside your loop to change someVar to false. But only you know what that condition is. The syntax would be:
let someVar = true
while (someVar == true){
let rotate = SKAction.rotate(toAngle: angle - CGFloat(M_PI_2), duration: 1)
crank.run(rotate)
if someCondition == isMet { // THIS IS FOR YOU TO DECIDE!
someVar = false
}
}
I ended up rewriting it completely and using SKAction.repeatForever to run an SKAction (to rotate) and that terminated only if the condition was false.
crank.run(
SKAction.repeatForever (
SKAction.sequence([
SKAction.wait(forDuration: 0.1),
SKAction.run({
let angle = atan2(self.point.y - crank.position.y , self.point.x - crank.position.x)
let rotate = SKAction.rotate(toAngle: angle - CGFloat(M_PI_2), duration: 0.25)
crank.run(rotate)
if(!(crank.frame.contains(self.point))) {
self.removeAction(forKey: "New Thread")
}
})
])
),
withKey: "New Thread"
)
I think the existing answers are missing the point here. You have two "threads" you are dealing with: the active thread running the routine (which will keep pumping new rotate actions onto the actions list for the node as fast as it can) and the action processing thread (which is really not a "thread" per se but can be imagined as one for the purpose of this question) which is where the rotate actions are actually executed.
Essentially, in a given timeslice, the "main" execution thread might pump 100k "rotate" actions onto your node's action list, and the SpriteKit engine will process all of them at the same time as efficiently as it can (I believe by removing duplicate actions but I'm not positive on that).
The effect is that you are doing a lot more work than you have to, and burning CPU in both your spin loop and in the SKAction processing code trying to recover from the millions of actions added to the node every time it comes up to process.
Replace it with a repeat action, as Fahim suggested, and you'll be good. Then you just need a trigger of some sort to stop the action (give it a name to end just the one action, or stop all actions on this node when the trigger fires).
I solve this problem using more singletong. For example SKView() inside the loop in singletong.
Alright I'm offically stumped. I've been able to figure out my problems myself in the past but I'm lost on this one.
I'm trying to flip a child sprite's xscale. I want the flip to occur when the child's x position is negative. With the code below, the sprite does flip, every time the sprite reaches negative position, it loops back and forth flipping until reaching positive again.
I've tried numerous variations, but this is the code in it's simplest form. Any help or alternatives would be appreciative.
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
let pin = childNodeWithName(Pin1) as SKSpriteNode!
let guyPoint = guy.convertPoint(guy.position, fromNode: pin)
if guyPoint.x <= 0 {
guy.xScale = -1
}
else {
guy.xScale = 1
}
}
So if it is constantly flipping it's probably an issue of coordinate space. So check to make sure your convertPoint method is accurately returning the point you want. I would use println() to see what's going on there.
Probably what's happening is you want to flip the xScale when the child node is negative in the scene space or something (i.e. when the child is off the screen) but instead guyPoint might be the position of the child in its parent's coordinate space (so relative to the parent).
Also try with and without the else{} part to see if that changes anything.
I went through the docs and couldn't find anything.
Is it possible to create a custom transition?
I have to simulate a throw with custom easing etc.
In cocos2d I was able to just create a custom action, with corona I'm puzzled.
The docs are quite silent on the topic. However, if you do some trying out, you will find out that a custom easing function takes four parameters (only nil from the fifth parameter and up). Some playing around reveals that a custom easing function looks like this:
function easer(currentTime, duration, startValue, targetDelta)
...
end
Explanation
currentTime / duration: duration is self-explanatory, and currentTime is simply [0..duration] during the course of the transition.
startValue: Snapshot of the value at the beginning of the transition.
targetDelta: This is the value of the target-value, minus the startValue, i.e. the distance the easing-function "has to walk"
Annotated Example
Say you have the following code:
foo.frob = 1
transition.to(foo, {time=1001, frob=0.25})
I.e., you want a transition of foo.frob of [1..0.25]. Then:
function easer(currentTime, duration, startValue, targetDelta)
-- currentTime: [0..1001]
-- duration: 1001
-- startValue: 1
-- targetDelta: to-from = 0.25-1 = -0.75
return startValue + (currentTime/duration) * targetDelta -- a linear interpolator
end
Return Value
The return value should be startValue in the beginning, and startValue+targetDelta at the end. It is perfectly allowed to leave that range; however, once the transition stops, it automatically becomes startValue+targetDelta, so make it startValue and startValue+targetDelta at the beginning and end.
But you can be creative between the start and end, and let the function bounce back and forth, for example, like some of the included easing functions already do.
Well the answer is in the docs.
One of the params to transition.to is easing, which can be a custom function.