Following other object with delay in Unity - c#

I'm making a 2D game in Unity, and attempting to have one character move after another in order to attack them. In order to make this movement look natural, I want to add a delay, i.e. character follows the exact path other character took, but 0.5 seconds behind.
Since I'm utilizing the State Pattern for my characters behaviour, the movement logic is in a scriptable object. This means I don't directly have access to Update() or IEnumerator, but I work around this by passing in a reference to a MonoBehaviour script attached to the characterGameObject (not sure if this part is relevant, but included just in case there was some weird side effect that I didn't know about).
I first tried to use IEnumerator, with every Execute() call of the scriptable object (which occurs once every game tick) starting a couroutine which first waited for a set amount of time, and then moved the object.
void Execute(StateController stateController){
Vector3 movementVector =
Vector3.MoveTowards(actor.transform.position,targetWithOffset,
Time.deltaTime);
stateController.StartCoroutine(stateController.MoveTorwards(movementVector,
delay));
}
public IEnumerator MoveTorwards(Vector3 movementVector, float delay)
{
yield return new WaitForSeconds(delay);
gameObject.transform.position = movementVector;
}
However, this resulted in an extremely weird glitchy movement, where the character constantly teleported around itself as it moved torwards the target.
Does anyone have insight into this? Am I missing a fundamentally simple implementation, or was my method correct and the glitchy movement has come from a side effect (doubtful, because the code works perfectly without the IEnumerator, and the glitch still occurs when the delay var is set to zero.

character follows the exact path other character took, but 0.5 seconds
behind.
Step 1: Define what the "exact path" is.
Implement a "consumable" point-to-point path structure (ie Queue<Vector3>), and keep recording the path of the first character to it by recording it's current position on an update loop (ie Update(), directly or indirectly).
Step 2: Try to "consume" the path from oldest node to newest.
For now, ignore the idea of a delay; just make sure that the path system to work, and that the movement looks right.
On each update (Update() or indirect) of the follower entity, move towards the next node in the path until it's reached; when it is, "consume" that node (remove from "path", ie .Dequeue()), and any next nodes that are so close as to be considered "reached"; this, obviously, will make the entity start walking towards next node, if there is any "unreached" node left.
Step 3: Delay the following of the path at start and after the path is empty (and/or based on events & triggers if you need more than that).
When the path goes from a length/count of <=1 nodes to >1 nodes, before you start following the first (or next) segment, do the delay; this will create the effect you're looking for.
If the path's length ever gets <=1 again, it means it's being consumed immediately upon creation, which means the "follower" entity has reached the "followed" entity. In this case, from your description, the "follower" entity attacks the "followed" entity; meaning the game is not instantly ended; in that case, to allow the "followed" to distance itself again (as is implied should be the case) after it starts moving, the delay is applied again before the "follower" starts following. --- This approach to the implementation of delay makes the behavior happen automagically to this case, as it's the same check as is done at "start" (actually a loop); no need for secondary checks.

Related

destroy disconnected parts from main part

I'm working on some kind of 2D sandbox game in "Unity". In this game, you can create your battle figure like "robocraft" .
Details;
You can create your battleship on the another interface. if click "play", works "save" and "dontdestroyonload". Main Part is fixed. Other parts are child and in same tag with main part if they are unified eachother and main part. I used for this "collision stay".
And i want to create physics like in this picture;
[1]
[1]: https://i.stack.imgur.com/OhMMk.jpg
long story short; If below or above green part stay still, grey parts stay still because of connection but destroy both of them, all grey part must destroy.
I'm trying to use "flood fill algorithm" but I didn't know how to integrate to my codes.
Do you know any other solutions or can you give any example about "flood fill" for kind of this problems?
Already thanks for the people who trying to help.
My take on flood filled algorithm for your case would look like this:
Determine neighbours for each part. It will be maximum of 4 parts, or 8 if adjacency by corners also counts.
Create a list of neighbours and you can use OnCollisionStay to populate each list with neighbours.
When battleship is hit, this is where algorithm starts.
Create a Queue<Part> (or whatever collection suits you)
For each destroyed part
1.1) For each destroyed part's neighbours
1.1.1) Push its neighbours to the queue
1.1.2) Take the the first element from the queue. Mark it with flag as checked, and push it to the new checkedQueue.
1.1.3) Check if the part in question is a base part. If it is, it means there's a connection from neighbour of the destroyed part to the base, and those parts don't need to be destroyed. Exit the loop.
1.1.4) If it's not, push it's neighbours to the initial queue.
Continue with checking all parts. If you run out parts in the queue without exiting, it means there's no connection to the main part, and all parts on checking queue should be destroyed.
Obviously don't check or push parts that already have checked or destroyed flags. Be careful not to analyze all damaged part's neighbours at once, or you will end up with all parts connected to the core :) Also you might need to clear queues at appropriate times as well as reset flags when needed.
Hope you can read through that pseudo code, formatting on mobile is a challenging task. It probably isn't the most optimised code in the world, but it can serve as a good start.

Use c# to animate instead of Animator in Unity

Well I know animator system in Unity is very useful for many things but I find myself having my own state machine in the code and somehow the state machine that the animator provides is not accurate due to blend time maybe I dont know, so I find often my character being in state 2 in the animator state machine and state 0 in my own state machine and its crazy as I cant seem to make it match in limit cases when its about to end the action. So I would like to know if there is a way to just say with code "play this animation from frame A to frame B" and loop it or not loop, that would be much better for me, of course I will lose all the blend features but really I will be better, all I can fin in the docs refer to using the animator so far. Thanks a lot for any help regarding this =)
Edit: Forgot to add that I found Animation.Play but apparently this only play animation saved on separate files like when we use the Animation timeline to record a certain motion, but I have a character with a lot of frames there and I dont think it serves in this case (or in my tests it never finds the specified animation at least, maybe i miss somethnig)
before anything, you can your own state machine with Animator. in fact, you don't need to two different state machine for your purposes. (Watch this video here)
and about your question, I found a good answer here: Link
From what I've seen you can either do AnimationState.normalizedTime
which returns the progress of an animation on a scale of 0 to 1. So if
you have a 30 frame animation and you want frame 15, you can do if
(normalizedTime == 0.5)* Or the better and more reliable option is to
use AnimationEvents that fire on specific frames.
*You won't really be able to do this if we're dealing in floats--You can only get the approximate value or you'll have to check greater
then or equal to 0.4 AND less then or equal to 0.6 because the
animation could go faster than the current frame rate or the
normalized time value could be 0.50000001 because of the nature of
float values.

Simulate movement of game object as if server handles requests with lag

Question: Can anybody give me an idea about how I can write an custom algorithm, to move an object from point A to point B with latency?
I am currently using a pretty simple algorithm:
While(input is held) Add a point to current existing List of points
Check if the list exceeds the maximum offset (a given number of points) ->
a.Move the object over the 0 index point. b.Delete the 0 index point.
Loop back to 1.
But this algorithm does not give me desired results.I am looking maybe for some kind of math expression to do that lag simulation, but I am not really sure can it be produced with math anyway so I headed first here to ask the question.
Assuming you have some sort of user input and way to process events.
One approach is to explicitly delay user input events (or any other events) to some later time. I.e. when user clicks to send game object to new position instead of setting it as new immediate target you can put action into list of future events "Move to point B, starting CurrentTime + Delay".
As result your code will not be aware of the request to change destination and continue moving object to its previous target till "Delay" time passed.

Optimising movement on hex grid

I am making a turn based hex-grid game. The player selects units and moves them across the hex grid. Each tile in the grid is of a particular terrain type (eg desert, hills, mountains, etc) and each unit type has different abilities when it comes to moving over the terrain (e.g. some can move over mountains easily, some with difficulty and some not at all).
Each unit has a movement value and each tile takes a certain amount of movement based on its terrain type and the unit type. E.g it costs a tank 1 to move over desert, 4 over swamp and cant move at all over mountains. Where as a flying unit moves over everything at a cost of 1.
The issue I have is that when a unit is selected, I want to highlight an area around it showing where it can move, this means working out all the possible paths through the surrounding hexes, how much movement each path will take and lighting up the tiles based on that information.
I got this working with a recursive function and found it took too long to calculate, I moved the function into a thread so that it didn't block the game but still it takes around 2 seconds for the thread to calculate the moveable area for a unit with a move of 8.
Its over a million recursions which obviously is problematic.
I'm wondering if anyone has an clever ideas on how I can optimize this problem.
Here's the recursive function I'm currently using (its C# btw):
private void CalcMoveGridRecursive(int nCenterIndex, int nMoveRemaining)
{
//List of the 6 tiles adjacent to the center tile
int[] anAdjacentTiles = m_ThreadData.m_aHexData[nCenterIndex].m_anAdjacentTiles;
foreach(int tileIndex in anAdjacentTiles)
{
//make sure this adjacent tile exists
if(tileIndex == -1)
continue;
//How much would it cost the unit to move onto this adjacent tile
int nMoveCost = m_ThreadData.m_anTerrainMoveCost[(int)m_ThreadData.m_aHexData[tileIndex].m_eTileType];
if(nMoveCost != -1 && nMoveCost <= nMoveRemaining)
{
//Make sure the adjacent tile isnt already in our list.
if(!m_ThreadData.m_lPassableTiles.Contains(tileIndex))
m_ThreadData.m_lPassableTiles.Add(tileIndex);
//Now check the 6 tiles surrounding the adjacent tile we just checked (it becomes the new center).
CalcMoveGridRecursive(tileIndex, nMoveRemaining - nMoveCost);
}
}
}
At the end of the recursion, m_lPassableTiles contains a list of the indexes of all the tiles that the unit can possibly reach and they are made to glow.
This all works, it just takes too long. Does anyone know a better approach to this?
As you know, with recursive functions you want to make the problem as simple as possible. This still looks like it's trying to bite off too much at once. A couple thoughts:
Try using a HashSet structure to store m_lPassableTiles? You could avoid that Contains condition this way, which is generally an expensive operation.
I haven't tested the logic of this in my head too thoroughly, but could you set a base case before the foreach loop? Namely, that nMoveRemaining == 0?
Without knowing how your program is designed internally, I would expect m_anAdjacentTiles to contain only existing tiles anyway, so you could eliminate that check (tileIndex == -1). Not a huge performance boost, but makes your code simpler.
By the way, I think games which do this, like Civilization V, only calculate movement costs as the user suggests intention to move the unit to a certain spot. In other words, you choose a tile, and it shows how many moves it will take. This is a much more efficient operation.
Of course, when you move a unit, surrounding land is revealed -- but I think it only reveals land as far as the unit can move in one "turn," then more is revealed as it moves. If you choose to move several turns into unknown territory, you better watch it carefully or take it one turn at a time. :)
(Later...)
... wait, a million recursions? Yeah, I suppose that's the right math: 6^8 (8 being the movements available) -- but is your grid really that large? 1000x1000? How many tiles away can that unit actually traverse? Maybe 4 or 5 on average in any given direction, assuming different terrain types?
Correct me if I'm wrong (as I don't know your underlying design), but I think there's some overlap going on... major overlap. It's checking adjacent tiles of adjacent tiles already checked. I think the only thing saving you from infinite recursion is checking the moves remaining.
When a tile is added to m_lPassableTiles, remove it from any list of adjacent tiles received into your function. You're kind of doing something similar in your line with Contains... what if you annexed that if statement to include your recursive call? That should cut your recursive calls down from a million+ to... thousands at most, I imagine.
Thanks for the input everyone. I solved this by replacing the Recursive function with Dijkstra's Algorithm and it works perfectly.

Sight range, player position update

I'm coding a server for a multi-player RPG, and I'm currently struggling with implementing a sight range. Since some maps are rather large, I have to limit what the client sees. My approach:
If I get new coordinates from the client, I save them as the destination, together with a move start time. Once every x ms I go through all creatures in the world, and update their current position, after saving the position they were at the last time I've updated them. Basically I calculate the new position, based on move start time and speed, and write those in the current position variables, while saving the new start time. Once this update is done, I'm going through all creatures which moved, aka those who have a different position than at the last update. In a sub-loop I go through all creatures/clients again, to check if I have to notify them about a (dis)appearing creature. At the moment I'm running this update every 100ms.
This approach is working, but I have a feeling it's not the best way to do this. And I'm not sure what will happen once I have a few thousand creatures (players, monster, etc) in the world, which have to be updated and checked.
Since I weren't able to find resources about this particular problem, I'm asking here.
Is this approach okay? Will I run into problems soon? What's the standard to do this? What's the best way?
Eric Lippert had a really good series of posts on shadowcasting that might be helpful in approaching/solving this.
You may want to consider using quadtrees to split the game world into sections based on the areas that player characters can see. Then you don't need to loop over every creature in the game all the time; you only need to loop over the ones within the section that the player character in question is located in, and any adjacent ones in case something crossed the boundary.
I haven't done this sort of coding personally myself, but I did work with someone who did this in a space combat game for which I was developing a GUI!

Categories

Resources