I have a game with two players, each player has a score represented as a Text.
When one score changes, I want the score animate so i'm using ScaleEffect.
But in order to have the animation run I need to change a State variable. And I want this state to reset after the animation finishes so I could call it again afterwards.
Is there a way to do that without a asyncAfter? This feels very primitive and unsafe.
Related
I have written several methods does separate animations in my scene. However, I want to have each animation play after the previous one is finished.
Like if I have 2 different animation methods like moveObject1(x) and moveObject2(x) where x is the amount the object will move, how could I tell if moveObject1 is done moving x amount to run moveObject2?
I have a game that requires the player to roll two die. As this is a multiplayer game, the way I currently do this is have 6 animations (1 for each die's outcome). When the player clicks a button, it sends a request to my server code. My server code determines the die's outcome and sends the results to the client. The client then plays the corresponding animations.
This works ok, but has some issues. For instance, if the server sends back two of the same values (two 6's, for example) then the animations don't work correctly. As both animations are the same, they overlay each other, and it looks like only one die was rolled.
Is there a better way to do this? Instead of animations, using "real" dice? If that's the case, I always need to be sure to "pre-determine" the outcome of the dice roll, on the server. I also need to make sure the dice don't fall off the table or jostle any of the other player pieces on the board.
thanks for any ideas.
The server only needs to care about the value result, not running physics calculations.
Set up 12 different rolling animations:
Six for the first die
Six for the second die
Each one should always end with the same modeled face pointing upwards (the starting position isn't relevant, only the ending position). For the latter steps you'll probably want to adjust the model's UV coordinates to use a very tall or very wide texture (or just a slice of a square one). So not like this but rather all in a line 1-2-3-4-5-6.
The next step is picking a random animation to play. You've already got code to run a given animation, just set it to pick randomly instead of based on the die-roll-value from the server:
int animNum = Mathf.Floor(Random.Next()*6);
Finally, the fun bit. Adjusting the texture so that the desired face shows when the animation is done. I'm going to assume that you arrange your faces along the top edge of your square texture. Material.SetTextureOffset().
int showFace = Mathf.Floor(Random.Next()*6); //this value should come from the server
die.renderer.material.SetTextureOffset(1f/6 * showFace,0);
This will set the texture offset such that the desired face will show on top. You'll even be able to see it changing in the inspector. Because of the UVs being arranged such that each face uses the next chunk over and because textures will wrap around when reaching the edge (unless the texture is set to Clamp in its import settings: you don't want this here).
Note that this will cause a new material instance to be instantiated (which is not very performant). If you want to avoid this, you'll have to use a material property block instead.
You could simulate the physics on the server, keep track of the positions and the orientations of the dice for the duration of the animation, and then send the data over to the client. I understand it's a lot of data for something so simple, but that's one way you can get the rolls to appear realistic and synced between all clients.
If only Unity's physics was deterministic that would be a whole lot easier.
this is an algorithm/data structure question about making different animations at the same time. For example, a ball is falling down one pixel in a millisecond, a bullet is moving 5 pixels in a ms, and a man is moving 1 pixel in 20 milliseconds. And think that there are hundreds of them together. What is the best way of putting all animations together, moving what we need to move in one function call, and removing the ones whose animation is completed? I don't want to create a thread for each one. What I want to do is to create one thread moving all items and sleeping until an object needs to be moved.
Note: I'm using Java/Swing, printing objects and images in JPanel.
I recently did something similar in Python. I don't know if this is the best method, but here's what I did.
Create an abstract Event class with the following public interface:
tick - calculates how much time has passed since the last tick. Perform work proportional to that time span. This should be called frequently to create the illusion of smooth movement; maybe sixteen times a second or so.
isDone - returns true when the Event has finished occuring.
Make a subclass of Event for anything that takes more than one frame to finish. Rotating, scaling, color changing, etc. You might create a TweenEvent subclass of Event if you want to move an image from one part of the screen to another. During each tick, redraw the image in a position farther away from the original position, and farther towards the destination position.
You can run many Events concurrently, like so:
Array<Event> events = new Array<Event>();
//add a bunch of TweenEvents here - one for a bullet, one for a ball, etc.
while(True){
Sleep(1/16);
for(Event e in events){
e.tick();
if (e.isDone()){events.remove(e);}
}
}
I am implementing a turn based game, there are two sides and each side has several units, at each specific moment only one unit can move across the board.
Since only one unit can move at a time, after i figure out where it should go, as far as the simulation is concerned it Can instantly be teleported there, but playing the game you would want to see the unit moving so that you realise who moved and where he went.
The question is, would you put the movement algorithm (eg interpolating between 2 points in N seconds) in the model and then have the view show the unit in the interpolated position without even knowing that it is moving, or teleport the unit and notify the view that it should show the unit moving as best as it wants.
If you would take the second approach, how would you keep the simulation from running too far ahead of the view, would you put the view in command of resuming the simulation after the movement ended?
Thanks in advance, Xtapodi.
Ah, yet another example that reminds us that MVC was never originally designed for real-time graphics. ;)
I would store the current position and the previous position in the model. When the object moves, the current position is copied into the previous position, the new position is copied into the current position, and a notification is sent to the view that the model has changed. The view can then interpolate between the old and the new position accordingly. It can speed up, slow down, or even remove the interpolation entirely based on the specific view settings, without requiring any extra data to be stored within the model.
Rather than storing the current position and the previous position, you could instead just store the last move with each unit, and the move itself contains the previous position. This is probably more versatile if you ever need to store extra information about a move.
What you probably want is to have the unit image move each frame. How far to move the image each frame is similar to your interpolation.
unitsPerSecond = totalUnits / (framesPerSecond * totalSeconds)
So if I want to move an image from position 0 to position 60 in 2 seconds and my framerate is 30, I need to move 60 units in 60 frames, therefore my speed is 1. So each frame, I move the image 1 unit, and if moving the unit will take me beyond my destination, simply set my location to my destination.
The data model in my program has a number of discrete states, but I want to animate the transition between these states. While the animation is going on, what the user sees on the screen is disconnected from what the underlying data is like. Once the animation is complete, they match up again.
For example, let's say we have a simple game where Snuffles the bunny hops around on a 2D grid. The model of Snuffles contains integer x/y coordinates. When the player tells Snuffles to hop north, his y-coordinate is decremented by one immediately. However, on the screen, Snuffles should at that point still be in his old location. Then, frame by frame, Snuffles proceeds to hop over to his new location, until he is shown in the location his model states.
So usually, when we draw Snuffles, we can just look up his coordinates in his model. But when he's hopping, that coordinate is wrong.
If there is only ever one thing moving on the screen, I can just about get away with freezing the entire game state and not allowing the user to do anything until Snuffles has finished hopping. But what if there is more than one bunny on the screen?
It gets worse if elements interact, merge or split. If Snuffles magically merges with a hat to become a potato, at which point does the data model delete the bunny and the hat, and add the potato? If it does so immediately, the view instantly loses access to information about Snuffles and the potato which it still needs to draw the animation of the magical merger.
I have come across this problem multiple times while implementing animated GUIs, especially games, and have found no satisfactory solution.
Unsatisfactory ones include:
Do the changes immediately, but then suspend any further changes in the model until the animation has resolved. Makes things unresponsive and doesn't work if more than one thing can move or things interact in complex ways.
Merge the model and the view - Snuffles gains floating-point coordinates, and probably a z-coordinate to indicate how far up he is. The model's rules become massively more complex as a result, as the model can no longer make concise statements like "you cannot hop north if there is a wall at (x, y - 1)". Any change to the rules takes much longer, and development slows to a crawl.
Keep what amounts to a duplicate of the data in the view. SnufflesModel has integer coordinates, but SnufflesSprite has floating-point ones. End up duplicating some of the model rules in the view and having to keep them in sync. Spend lots of time debugging to make sure that SnufflesModel and SnufflesSprite don't de-sync under some rare circumstance.
My best bet at the moment is option 3, but it hardly strikes me as elegant. Thoughts?
You would need a stronger model to account for the time component of changes:
Each sprite needs to maintain a queue of animation actions it is supposed to carry out. Adding animations to the queue should be a zero-time action (game time). Queued animations proceed on a frame-by-frame basis when they get a tick from the animation clock. Queuing lets you separate the model from the graphics subsystem and the animations.
Each animation in the queue carries with it a model action to perform when the animation is complete. Some languages make that easier, e.g. with anonymous functions in C# or JavaScript. In other languages, you could use a callback instead. The model action lets you specify how the model would change when the animation completes.
Sprites can carry high resolution coordinates (e.g. floating point), while the model stays with integer ones. Sprites don't need to know anything about the game rules though -- the queued animation-completion model-actions deal with that.
Model entities should be able to account for a transitional states: appearing, disappearing, and moving. This lets you avoid checking the rules for objects in transition.
To implement Snuffle's quest, you could then:
User asked to move Snuffle north? -(1) check that the rules allow the move, (2) queue a move animation on Snuffle's sprite, coupled with a landing model action. Put the bunny's model into a transitional moving state.
Snuffle's landing model action brings the bunny's model back to a normal state, and checks the landing spot and the rules. Finding a hat, it queues a potato appearance animation (the "merger") and two disappearance animations for the bunny and hat.
The model actions for the disappearance animations delete the bunny and hat when complete.