Changing Sprites using scripts in Unity2D C# - c#

I am wanting to make a birds-eye view pixel-art game.
I currently have two sprite sheets set up, and split and whatnot
groundSheet and characterSheet these are split up into
ground_0_0_0 (A concrete floor)
ground_1_0_0 (grass)
character_0_0_0 (man idle animation frame 1)
character_0_0_1 (man idle animation frame 2)
character_0_1_0 (man run animation frame 1)
character_0_1_1 (man run animation frame 2)
character_1_0_0 (woman idle animation frame 1)
character_1_0_1 (woman idle animation frame 2)
character_1_1_0 (woman run animation frame 1)
character_1_1_1 (woman run animation frame 2)
The numbers after are a note as to:
first number - the main set of sprite animations (eg man)
second number - the animation set in use (eg run or idle)
third number - the frame of said animation.
(the ground has this as i plan to have animated grounds late on)
Now, I wish to make a script for the character (and ground alike) that has an editable value that is view able in the unity editor, for example how things like the sprite renderer has sprite, colour etc. Which dictates what first number to use (see above) what second number and the delay for the animation of the third number. This will then tell the sprite renderer what pictures to load and how quickly to load them. I also wish for the script to scan for the file starting with for example character_0_0_ and then count how many files after it, so it knows what to do when animating. I would like this script to be checking for a change in one of the variables viewable in the unity editor to change and as soon as it does it checks everything it needs for an animtion.
Something else could be done where there is only 1 box to edit in unity, which you put character_0_0_ or ground_1_0_ or something similar, and it checks everything that way (it also makes the script universal, and usable on the ground, character and walls (which I am adding later)).
This may seem confusing, but it make sense for me and many of you will probably mention a much easier way to do animations and such, but please only say these if it does what I want above.
For scripts and such my file layout:
/Assets
/scripts
ground.cs
character.cs
/sprites
characterSheet.png
character_0_0_0
character_0_0_1
character_0_1_0
character_0_1_1
character_1_0_0
character_1_0_1
character_1_1_0
character_1_1_1
groundSheet.png
ground_0_0_0
ground_1_0_0
(For some reason Stack overflow said the above was code, so i had to make it as that)
ground.cs and character.cs are the scripts in which I want to made as explained above.
In my object view thingy I have
Main Camera
ground
character
I am practically a newb to C# and JS I know bascially the grammar of C# (like where to use {} and put ; at the end of the lines). If you help me with this, i request that you explain the script, like use the // thing to simply explain what each command does, I know a few but not all of them. And I know someone is going to say it is really well documented in tutorial X and such, but most tutorials are not in unity 5 and while helping with the matter do not touch on it exactly.
Thank you for your help, if there is anything about this question/request that you do not understand (It is pretty complex) I will explain.

Maybe I am completely wrong, but it seems to me that you are trying to recreate an Animation system.
Is there a specific reason for which you wouldn't use Unity's animation system?
You can do everything that you describe here with it (change sprite, choose animation speed). And you would have almost no code to write. Just drag and drop you sprites in the editor for a start
EDIT - answer to first comment:
What you should do is create all the animations you need. Then in the animator, you choose which condition will trigger a transition to another animation (for instance, boolean jump is true will transition to animation jump). Then in your code you can call GetComponent().SetBool("Jump", true).
To have different character, you can create different gameObjects (one per character). They all have a different animator with animations specific to the character.
The other solutiojn if you really want one one gameObject and one animator is that you also add string condition to you animation (example, if character=="character1" and jump==true, transition to jump animation).
If I were you I would really focus on testing and learning all you can do with Unity animator. I can't think of a case were you would need to recreate the animation system yourself

Your question was long winded and hard to understand but ill try to help,
firstly if you want editable values in the unity editor I would Suggest using a serialized structure of information like this
[System.Serializable] // this makes it viewable in the inspector
public struct Sprite_Manager;
{
public Sprite[] Render_Sprites; // array of sprites to store sprites
public SpriteRenderer S_Renderer;
public float Anim_Delay;
}
public class Character : MonoBehavior {
Sprite_Manager SMG = new Sprite_Manager(); // instantiate a new instance of the struct
void Set_Sprite()
{
for(int i = 0; i < SMG.Render_Sprites.Length; i++)
{
SMG.S_Renderer.sprite = SMG.Render_Sprites[i];
}
}
void Update
{
Invoke("Set_Sprite", SMG.Anim_Delay);
}
}
Not sure if this is exactly what your looking for but this is one way you could setup a structure of sprite based information and use Invoke to setup some sort of delay when passing new sprites to the renderer.

Related

OnTriggerEnter2D working only when the game starts, i want it to check for collisions every frame

I am working on a game in unity, a type of sliding number puzzle where you have to line up each piece in ascending order. My code of checking collisions is only working when I start the game, so if I move a piece, it won't tell the near pieces that I moved the near piece. I hope you understood my problem, every help is appreciated. Thank you.
This is how my code looks with the up check. I
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.name == "Piece" || collision.gameObject.name == "Up_Collider")
{
piece_Script.Collide_Up = true;
Debug.LogError("Up");
}
else
{
piece_Script.Collide_Up = false;
}
}
I Thought that the else statement will solve this problem but it didn't.
Make sure all the things I write below are correct in your project:
1- You are using "2D" colliders on both objects.
2- At least 1 of the objects has a "Rigidbody2D".
3- IsTrigger Checkbox is active in your collider.
4- You are using the correct Tag.
5- Check layer collision matrix in - Edit > Project Setting > Physics2D.
And it is better to use tag instead of name
Based on your code in your question and your video, I see at least a couple issues.
First, there's an issue with how you're moving pieces. Your movement code for a Piece is:
Piece.transform.position = Vector3.Lerp(a, b, t);
This is not correct if you want to trigger collider events. These require interactions with rigidbodies, which means you should instead be changing the position of the piece's rigidbody with Rigidbody2D.MovePosition(). This will move your rigidbody within the physics system, which means taking into account collisions/triggers.
So (assuming you get the rigidbody for each Piece when you initialize them), your code might look like:
// Note also that I used Vector2 here - it's best you keep it consistent
pieceRigidbody.MovePosition(Vector2.Lerp(a, b, t));
Second, OnTriggerEnter2D() is not fired when two colliders stop touching. So I don't see your "else" condition being particularly useful. To achieve that with your current code, you could theoretically introduce OnTriggerExit2D() to take care of the "else" condition. However, you run into complications because while moving, a Piece may Enter and Exit the same directional colliders of two other Pieces before coming to rest. You'd have to take into account the order that occurs to get an accurate final state.
While workable, I have an alternative approach to suggest: Abandon using Trigger Collider events, and only check for a valid move at the time a Piece is clicked. Eliminate the collider event handlers, and just execute a Physics2D.OverlapBox() in each position around a Piece when it is clicked. If the position is occupied by another piece or an edge, that's not a valid move. If there is a position without something blocking it, then move the piece there.

How to reset sequence of animations when target is lost

I am using Unity and Vuforia, and would like to make an animation on AR object that starts when target is found and resets when target is lost so that, when target is found again the animation starts from the beginning.
In order to make animation start only once target is found, I selected the option "Cull Completely" in the Culling Mode property of the animator component. But I can't manage to reset the animation when target is lost ! I have tried modifying the DefaultTrackableEventHandler script (the OnTrackingFound and OnTrackingLost methods) but it doesn't work.
So far I have tried :
Animation[] animationComponents = GetComponentsInChildren<Animation>();
foreach (Animation component in animationComponents)
{
component.Stop();
}
and some variations (animation name as a parameter of Stop method, animator component instead of animation component, ...).
Does someone know how to do this ?
Thanks for your attention :)
I know a way of doing what you want in a simpler way. Look for https://docs.unity3d.com/Manual/class-State.html
You will get the same results but in a different way using the animation states.
Then go to the animator window
And you can build something like that. Those are transitions between states, associated to an animation.
Take a look at this too https://docs.unity3d.com/Manual/class-Transition.html
So in your script you can access to the Animator with:
Animator MyAnimator = GetComponent<Animator>();
And in somewhere over your conditions in the game, you can do this:
MyAnimator.Play("Attack");
If that animation doesn't have a transition, it will your decision to make it a loop animation (it will repeat when ends) or it will stay in the position of the last frame of the animation.
With some conditions you might want to have, like the one in your question, you could do something like this.
if (Vector3.Distance(this.transform.position, myTarget.transform.position) >= 2f) {
MyAnimator.Play("Idle");
}
Warning: That Vector3.Distance may not be the best and fastest way of doing it, it's just as an example. Remember to always try to optimize your code with your project requirements.

How to control Unity Animation?

As far as I know, there are ways to manage Animation
Immediately,
Managing in the form of objects.
Managing with Sprite Images.
Is it effective to manage animations
in object format to manage character's joints in 2D animation?
What should I do to make it easier for me to understand Unity Animation?
As a beginner, we need a lot of data. I need your help. Help me.
I am going to explain the animation by manipulating GameObjects.
You need to add an Animator component to the GameObject you wish to animate. The animator component needs an animator controller. You also need to create an animation clip which represents an animation.(Animation controller is automatically created when you create an animation clip)
Now, to get started with animation you need to focus on animation clips. After you add an animation clip, you can record an animation into it. You do this by hitting the record button in the Animation window. While recording, any changes made to the GameObject will be recorded into the animation clip. (For example, you might move your GameObject). Any such change will create a key frame in the Animation timeline. The time point where key frame should be created can be changed.
Unity will interpolate the changes between two keyframes automatically.
However, there is also an animation curve which allows you to define how changes are applied between time points.
After you record animations you can define how transitions between different animations are made in the Animator Window.
unfortunably I am not really sure what your question is about?
For question this might be helpful:
https://www.youtube.com/watch?v=PuXUCX21jJU
Usually you have a Image File with the animation movements of your 2D Image object and using the "Sprite Editor" to cut them out for Unity.
You then add this Clip on a Animimation Component to be added to your "GameObject".
Since this is a "C#" question, maybe you want to know how to access this Compnent. The best is to use it in the "Init()" and add:
var anim = GetComponent();
Now you can use the "Animation" Component to play the configured Animation Clips.
I hope this helps you a little bit.

Unity modify animation at runtime

TLDR:
Basically, I use the same animation for all of the soldiers, but I want those animations to behave little different from each other, so all my soldiers won't behave all the same. Would i be able to modify those animation at runtime?
So I'm working on this RTS style game that has a group of soldiers, let's say charging. Since most of them using the same animation. Although I randomize the starting time of each animation, so they won't be played simultaneously. But everybody in the unit is still charging with the same animation. And it looks rather weird.
I wonder if there's a way that I can alter each animation a little bit on runtime, to the degree they swing their arm, for example, one of the soldiers would swing a few degrees more, and other will swing less.
I wonder if it's possible to do in unity at runtime. And if so, how would I do it?
Any suggestions would be appreciated.
First and foremost, replace your animation with animator controller.
Inside the animator, for example, you can add animation events. You can also define animation parameters. Based on the parameters you define, your character can switch between different animations. Lets take a look at an example now.
Put a script, SoldierAnimator, on your soldier that has reference to the animator controller.. Now, lets say that your soldier's 'loadGun' animation has 3 variations. You now assign a parameter to each animation. So 'crouchLoad', 'quickLoad' and 'stuckLoad' substates can be assigned parameter 'loadType' with values of 0, 1 and 2.
Assuming that you can go from "Any State" to 'loadGun' state with trigger parameter 'load', and your SoldierAnimator reaches a point where it has to load gun, you can do something like this:
public class SoldierAnimator : MonoBehaviour
{
public Animator _animator;
void someUserInputEvent()
{
//... Some code here...
loadGun();
}
void loadGun()
{
int animType = Random.Range(0, 3);
_animator.SetInt("loadType", animType);
_animator.SetTrigger("load"); //Now your animations are randomized
// You can also experiment with _animator.speed = xx, for
// different speeds of loading animation, probably randomized a
// little, but then add an event to end of the animation and
// on the event, set speed back to 1.
}
}
What i would suggest you to do is set up conditions such that when the conditions is met, certain actions would be performed.
Transitions define not only how long the blend between states should take, but also under what conditions they should activate.
You can set up a transition to occur only when certain conditions are true.
To set up these conditions, specify values of parameters in the Animator Controller.
Also you can try : ordered interuptions , transistion offsets or transistion duration to achive your goals.
Further edits:
In this case, your higher-level script will need to set the character's animation parameters so that the avatar does what's specified in the text file. It might even be better to use Animator.Play() or .CrossFade() to directly change the animation state rather than setting an animation parameter.
For example, lets say your character 3 twitches at time 02:49. Then at 02:49 the script on character 3 (but only on character 3) should either set a trigger parameter such as "twitch" to true, or play an animation state directly such as Animator.Play("twitch").
So in effect all your soldiers would have different scripts each assigned to them.
Scripts have public properties that you set in the inspector. You can define a property for the character's number. This value would be unique for each character.
does this answer your question? sorry if i still didnt get your question

Character slowly move up the ground using a humanoid animation type in Unity

I have a marine model used in my start project, which will uncontrollably lift off the ground when running. I import the fbx resources, set the animation type as humanoid and configured the avatar by automatically mapping, set up a animator controller that contains only a running animation. Here is about several seconds after playing:
But when using a generic animation type everything works fine. Any suggestions to fix this while still using the avatar system?
UPDATE:
Configure of my 3D model:
This is obviously caused by root motion. What happens is, one loop of your animation takes the character slightly higher. Adding these slight changes up, you get what you're getting. If you don't need root motion (doesn't look like you do), disable it (from the animator component's settings). If you do, either edit the animation to make sure it fits, or disable root motion along the Y-axis (you can do this from the animation's import settings).
In case you don't know what root motion is, it's when the root bone of your model has animations applied. You obviously can't create the entire animation of character running up and down your levels, and until recently (though not MUCH recently) characters where animated in-place, and moved procedurally via code (I know for a fact that Unreal Tournament 3 uses this method, as would any UDK user). Then, people started wondering how they could make their characters move more realistically? I mean, it's not like you walk forward at a constant rate of 4 km/h, you tend to slow down and speed up during different parts of the walk cycle. The same can be applied to video game characters using the technique known as root motion.
With root motion, you actually move the character forward during its animations. This will cause an animation to look really bad in max or maya, since the character will just snap back to its original place after a loop. However, this data is used intelligently in game engines: Rather than use the absolute position the animation yields, you take the velocity out of it between each two frames, and move your character based on that velocity (Unreal engine actually has a really neat acceleration mode for applying root motion, though I'm not really sure how that would be different from velocity mode). This will make your character move forward at the same rate the animation does, and thus you can actually animate the character's movement as well as its limbs and joints. Moreover, since you're using the velocity and not position data from the animation, it will look exactly as you'd expect it to. If you're interested in this technique, take a look at the Mechanim demo pack they have on the asset store. It makes extensive use of root motion to move the character around.
My company was having a similar issue but we still wanted to keep the "Apply Root Motion" toggle checked. When the same animation played on loop, the model stayed in place but if several different animations were played one after another, this caused the model to rotate / shift in position.
The solution for us was ticking these check boxes in the animation settings for each animation. Root Transform Rotation, Root Transform Position (Y), Root Transform Position (XZ).
I had the same issue a few days ago. I found out that the problem was the Apply Root Motion in the Animator script. Make sure it's unchecked.
Tag your player with "Player" in scene
and use this script
float y;
GameObject player;
void Start ()
{
player = GameObject.FindGameObjectWithTag("Player");
y = player.transform.position.y;
}
// Update is called once per frame
void Update ()
{
float diff = player.transform.position.y;
player.transform.Translate ( 0, 0,z - diff);
y = player.transform.position.y;
}
it is little hacky soultion but works!!
note: if you want to use y movement at some point just calculate and add it to diff variable.
For those who couldn't solve this issue with 'bake into pose'.
I tried 'Bake into Pose-Y', but it didn't work.
Meanwhile, in FBX > Animation > Motion, I set 'Root Motion Node' as 'Root Transform'(It was 'None' before), it solved my problem. Unity version is 2020.3.34f1.

Categories

Resources