Changing the players sprite with animator - unity3d

i have a 2d platformer with a player. The players default sprite is set to idle. There is 4 sprites and states in total --> idle, jumping, left, right.
Im trying to get the player to switch sprites depending on what their doing eg jumping or moving right.
This is my first time using unity and animator so im not experienced at all.
So each of my animations look something like this. 1 frame and one for each state:
And then I open up the animator:
Im not too sure what the arrows do but i figured its like a flow chart so you go from idle to left so i matched up the arrows. I then also made 4 booleans for each state.
Then on the script attached to the player, i added this code:
private Animator animator;
void Start () {
animator = GetComponent<Animator>();
}
//This is in the update function
if (!playerLeft && !playerRight && !jumping)
{
setAnimationState("playerIdle");
}
else if (jumping)
{
setAnimationState("playerJumping");
}
}
private void setAnimationState(String state){
animator.SetBool("playerJumping", false);
animator.SetBool("playerLeft", false);
animator.SetBool("playerRight", false);
animator.SetBool("playerIdle", false);
animator.SetBool(state, true);
}
So i made a function that cancels of the animations and switches it to the correct one which is called. You can see how i call it with jumping and i also have the same for left and right but i know they are all being called correctly from the animator.
In the animator, only the right grey box is running. I can see because it has a blue bar and its not switching animations. The booleans are switching but thats it.

On the top of my head:
You need a transition from right to left and left to right.
You need one from right, left and jumping back to idle.
You can click on the arrows and select which booleans need to be checked to enable the transition.
Fore each animation state you need to upload a spritesheet. You can drag and drop this in the animation tab. The animation will play untill there are no more sprites. It will then check if it can transition into another state or loop the current state. (Do note that you need to enable looping on each state, except jumping i guess?)

Welcome to Unity development :)
I don't want to make this too long, so let's just use playerLeft as an example.
So you've set the Idle state as the default state - meaning if all the booleans are false, the player is idle. But once you press the left key, you would want the player to transition from the idle state to the Left state.
First step is to click on the transition (the arrow) from idle to playerLeft.
Next, is to add the playerLeft boolean as the condition. This means that when the playerLeft boolean becomes true, we start transitioning from Idle to Left.
And finally, tinker with the code. We need to tell Unity to set playerLeft to true when we press the "D" button for example.
Update()
{
if(Input.GetKeyDown(KeyCode.D))
animator.SetBool("playerLeft",true);
}
We place it in the Update() method to make sure it runs every frame. Then, we have a condition where it waits for the player to press D.
There's still a whole lot to do after this such as doing return transitions but well, you'll figure out the rest as you go so don't hesitate to ask ;)

Related

How to create blur effect to all the scene except for one object (focus on that object)?

I want to create a blur effect similar to the picture below:
the picture is taken from this site:
https://forum.unity.com/threads/how-to-blur-specific-layers-only.555520/
I tried the post-processing profile and played around with the depth of field in the post-processing volume but it blurs all the scene.
I came across a YouTube Video that explains how to implement similar results to what I am looking for but things have changed drastically in the settings. For example, at 1:57 (minute and 57 seconds) he clicks on Add Additional Camera Data which I am struggling to find in the latest versions of LWRP.
I am using Unity version 2019.2.9f1
How can I achieve the result in the picture above? (Blurring all the scene except for one object)
Your guidance will be appreciated.
NOTE: My project is in VR using SteamVR and VRTK
Though your question is a bit broad I took some time to show you how it can be done.
First of all you will need to import the Post Processing package via the PackageManager
Window &rightarrow; PackageManager
Make sure to be in the All Packages view, search for post, find the Post Processing package and hit Install
Now first of all go to the Layer settings (Layers &rightarrow; Edit Layers)
and add two additional Layers: e.g. PostProcessing and Focused
Now to the cameras. Afaik it makes no difference whether you are in VR or not, usually you have one MainCamera that is moved along with your headset. If there should be two of them in your project setup just repeat the same steps for the second camera.
Make sure the MainCamera doesn't render the two added Layers &rightarrow; remove them from the Culling Mask
Add a new Camera FocusCamera as child to the existing MainCamera. This way it is automatically moved along with the main Camera.
RightClick on MainCamera &rightarrow Camera
It should have all the settings equal to the MainCamera except:
Clear Flags : Don't Clear
If you set it to Depth Only the focused object will always be rendered on top of everything, even if it is actually behind other objects in 3D space. You decide which effect you want here ;)
CullingMask : only Focused
Depth : Anything higher than the MainCamera so this camera is rendered on top of it
Make sure to remove the AudioListener component.
Finally add a new PostProcessingVolume to the scene. I would add it as child to the FocusCamera! Why? - Because this way it is automatically disabled together with the FocusCamera!
RightClick on FocusCamera &rightarrow; 3D Object &rightarrow; Post Processing Volume
Set its Layer to the added PostProcessing
enable Is Global so the distance to the volume doesn't matter and add a new profile by hitting new &rightarrow; Unity &rightarrow; Depth of field
In your case you want to overwrite the Focus Distance so check the box on the left and set a value close to the camera like e.g. 0.5
Until now nothing has really changed in your scene.
Now go to the MainCamera and, a component PostProcessingLayer and set the Layer to our added layer PostProcessing
Now everything should be blurred in your scene!
Almost ready to go! Now Disable the FocusCamera and add this script to it
using UnityEngine;
public class FocusSwitcher : MonoBehaviour
{
public string FocusedLayer = "Focused";
private GameObject currentlyFocused;
private int previousLayer;
public void SetFocused(GameObject obj)
{
// enables this camera and the postProcessingVolume which is the child
gameObject.SetActive(true);
// if something else was focused before reset it
if (currentlyFocused) currentlyFocused.layer = previousLayer;
// store and focus the new object
currentlyFocused = obj;
if (currentlyFocused)
{
previousLayer = currentlyFocused.layer;
currentlyFocused.layer = LayerMask.NameToLayer(FocusedLayer);
}
else
{
// if no object is focused disable the FocusCamera
// and PostProcessingVolume for not wasting rendering resources
gameObject.SetActive(false);
}
}
// On disable make sure to reset the current object
private void OnDisable()
{
if (currentlyFocused) currentlyFocused.layer =previousLayer;
currentlyFocused = null;
}
}
This will allow you to focus a certain GameObject on runtime by changing its layer to the Focused layer we added, the only one that is rendered by the FocusCamera. So this object will be rendered on top of the image without any blur effect!
For demonstration I just added this simple script to every cube object in order to enable focus on mouse enter and disable it on mouse exit:
using UnityEngine;
public class FocusMe : MonoBehaviour
{
[SerializeField] private FocusSwitcher focus;
private void OnMouseEnter()
{
focus.SetFocused(gameObject);
}
private void OnMouseExit()
{
// reset the focus
// in the future you should maybe check first
// if this object is actually the focused one currently
focus.SetFocused(null);
}
}
And here is what it looks like
as said I don't know exactly what your VR setup looks like. If you have to MainCameras simply add two child cameras to them. You still will need only one PostProcessingVolume and only one FocusSwitcher so you would probably move them to another object and handle the camera disabling etc differently but I hope the idea gets clear enough.
Use a separate camera for objects you don't want to blur and set a higher depth value.
Set the ClearFlags to depth only and in the CullingMask select the layer of that one object(or more objects). Obviously you would require to have a different layer for unblurred objects.

Can't make a panel animation work through clicking on UI button

I'm trying to make a "Try Again" button work with a panel animation that's supposed to go from transparent to thick black before loading the game scene again. But for some reason the animation is not running nor the load scene line.I'm finding it odd.
At first I thought the panel was blocking me from clicking the button, so I set it inactive as default, and activate it through script.
I think I've set the references correctly, one for the panel animator, one for the panel itself (to set it active), one for "OnClick" section of the tryagain button and assigning the correct function from it in the inspector.
public class Tryagainscript : MonoBehaviour
{
public Animator tryagain;
public AudioSource audios;
public AudioClip tsu;
public GameObject panel;
IEnumerator TryCo()
{
tryagain.SetInteger("try", 1);
yield return new WaitForSeconds(1.2f);
SceneManager.LoadScene("Game");
}
public void Trybutton()
{
StartCoroutine(PanelCo());
}
IEnumerator PanelCo()
{
panel.SetActive(true);
audios.PlayOneShot(tsu);
yield return new WaitForSeconds(0.1f);
StartCoroutine(TryCo());
}
}
The names of the variables might be confusing, but you get the idea.
This is the script I assign to the TryAgain button to run the "Trybutton()" function so it runs both coroutines, one at a time. The integer "try" referes to the animator in the panel to go pitch black.
As I said though, nothing is working from this code: the panel is not going pitch black nor the game is loading back.
Thanks in advance!
Edit:
I've changed the code to something simpler:
public void Trybutton()
{
StartCoroutine(PanelCo());
}
IEnumerator PanelCo()
{
audios.PlayOneShot(tsu);
panel.SetActive(true);
yield return new WaitForSeconds(1.2f);
SceneManager.LoadScene("Game");
}
Instead of changing animation states, I set the desired one as default and just set the panel active.
The wierd part is (because I don't have the knowledge to understand it), the TryAgain button belongs to a GameOver menu panel. When the game starts with this GameOver panel active (but not the fading to black one), the script runs just fine. On the other hand, when I play and lose on purpose, the game over menu pops up, I press the TryAgain button and all it does is play the sound reffered by "tsu" before "waitforseconds()". No panel, no scene restart, although in the Inspector the panel shows as Active and full black.
Thanks again for your responses!
So, I'm feeling kind of dumb right now. I figured that the panel animation wasn't running after the player died so I investigated around it. I remembered then that I'd set the timeScale to 0f when the player dies. That's why the fading panel was not animating and the scene was not restarting.
I did not think about this before because I did not know the scene could not load if the timeScale was set to 0f.
Thank you again for your time, attention and answers guys!
I'm a newbie at this still.
This is the standard way to use couroutines in Unity (Fade out example):
IEnumerator Fade()
{
for (float ft = 1f; ft >= 0; ft -= 0.1f)
{
Color c = renderer.material.color;
c.a = ft;
renderer.material.color = c;
yield return new WaitForSeconds(.1f);
}
}
Don't try to reinvent the wheel this is the standard way to do a Fade Out (I think you want a Fade In). Here its changing the alpha value (c.a) decreasing it 0.1 each 0.1 seconds.
Source: https://docs.unity3d.com/Manual/Coroutines.html

Unity Animation on Button Click returns to Idle animation

I have four buttons to select range of numbers. (clicked button should animate and stay scaled just to indicate which button is selected) I am trying to play animation on button click in unity. so when button is clicked, animation is played and returns to idle. But I do not want it to return to idle state instead I want it to remain at the last frame of on click animation clip(at last frame scale is 1.2). Loop time is unchecked.
I have assigned onclick animator play(string) in the inspector. Please help
also tried following code
public GameObject rangeBtn;
public Animator rangeBtnAnim;
private void Start()
{
if ((rangeBtn != null) && (rangeBtn.GetComponent<Animator>() != null))
{
rangeBtnAnim = rangeBtn.GetComponent<Animator>();
}
}
public void PlayAnimation()
{
rangeBtnAnim.Play("RangeSelectionButton_Pressed");
}
I would simply use this setup with Parameters
Make the PressedAnimation clip not Loop Time and use a bool parameter e.g. IsPressed. (One could also use triggers instead but in this case a bool is easier and saver - triggers stack ...)
Than the setup for the transitions:
Idle -> PressedAnimation
and PressedAnimation -> Idle
Than in your code instead you would set
rangeBtnAnim.SetBool("IsPressed", true);
or
rangeBtnAnim.SetBool("IsPressed", false);
to go back to idle.
Note the simplest way in fact of having animations (if they are not complex) would be to simply only have 1 single keyframe in Idle and also in PRessedAnimation. Unity would than simply make a transition animation interpolating between the values according to the transition duration settings.
Alternatively if your animations get more complex you would probably rather do something like
And for the two transitions
PressedAnimation -> StayPRessed
UnPressAnimation -> Idle
use the ExitTime
for the other two use the parameter
and
Something I used in my games. Let's say you have two animations: Idle and Animated.
You want your button, after Animated finishes, to stays on the last frame right ? Then you create a third animation, Animated_Remains, which contains only one frame, the last from Animated.
Then, in your Animation Controller, you put a transition between Animated (no loop) and Animated_Remains (looped). If you want the same behaviour when transiting from Animated to Idle, then you create a 4th anim, Idle_Remains.
So, after clicking on your button, it will play the Animated animation, and automatically transit to the Animated_Remains.
I did that when I had to move my Camera with an animation and make it stay at the last frame position.

Unity 3d OnClick to ignore specific layer (or fire only on specific laye

Is there a way to make standard unity OnClick even fire while ignoring specific layers?
For example, i have army of soldiers on layer "Units" and ground on Layer "Ground". When i click on soldier, it gets selected. Then i click on the ground, soldier moves there. But if i click on the ground obscured by another soldier, it fires even for that soldier rather than ground, cos he is closer to the camera.
Can i ignore "Units" layer without rewriting whole mouse click even handling and using my custom raycast?
EDIT:
code is here, dont thnk it will show anything but
static public void Interact2(Cell target) //this fires from OnClick
{
if (GameLogic.Mode == mode.move)
{
grid.MoveTo(target);
if (selected.actionsAvilable[action.move])
selected.actionsAvilable[action.move] = false;
else
selected.actionsAvilable[action.standard] = false;
GameLogic.Mode = GameLogic.mode.normal;
}
}
MORE EDIT:
void OnMouseDown() {
if (!UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject())
GameLogic.Interact2(this);
}
The PhysicsRaycaster/PhysicsRaycaster2D/GraphicsRaycaster components have an Event Mask property which allows you to limit the layers they raycast against. You should update that property from code when you want to block/allow certain layers.

Unity: How to detect mouse click in a script without attaching the script to an object?

In Unity, using C#, how do I detect a click anywhere in the screen, without attaching the script to an object?
To be specific, I am looking for individual clicks, not mouse downs.
e.g. the code below checks for mouse down, but I want clicks instead
// Update is called once per frame
void Update () {
// 1
Vector3 currentPosition = transform.position;
// 2
if( Input.GetButton("Fire1") ) {
// Do something
}
}
You are going to need a MonoBehaviour so that you can use the Update() function to your advantage. Just attach it to an empty GameObject, it is not uncommon for a game to have one empty GameObject that has a few scripts that handle certain things.
Check for GetMouseUp to count your clicks.