#Blinking indicator in Unity (every 2 seconds)
1 messages · Page 1 of 1 (latest)
Either swap the Sprite or make the Color darker
if you have a Sprite Renderer then just Reference it instead of the GameObject visualCueE
it has the field Color, just modify it
Yeah I have that. Would I swap the sprite using an animation cycle or literally replace it?
I was using a timer to decide when to change the color
`` void Update()
{
if (playerInRange)
visualCueE.SetActive(true);
if (Input.GetKeyDown("E"))
tristanIsCrouching = true;
else
visualCueE.SetActive(false);
Debug.Log("Tristan is crouching" + tristanIsCrouching);
if (this.playerInRange)
{
buttonETimer += Time.deltaTime;
}
if (this.buttonETimer >= 2f)
{
//darker here
}
if(this.buttonETimer >= 4f)
{
//change it back here
this.buttonETimer = 0f;
}``
Logic is when the timer is >2f or seconds, the sprite is changed to the darker color and then back after that
I'd just completely swap the Sprite/Color in the Sprite Renderer
But most likely just the Color since I can just define it in the code, no need to reference any additional sprites
With Colors you could even make a short Lerp so the transition would look nicer
Oh that seems nice! Is there a tutorial for the color swapping online? I'm not sure how to do it
I can't find one specifically for Sprites, most are for Ui
Changing a button color programmatically in Unity.
Udemy Courses:
https://www.udemy.com/course/unity-nosql-dynamodb-player-management-leaderboards-more/
https://www.udemy.com/course/unity-sql-database/
https://udemy.com/course/unity-aws-s3/
https://www.udemy.com/course/make-a-your-own-free-vpn-with-awscloud-computing/
https://www.udemy.com/cou...
This is the closest one I've found but is for UI buttons
spriteRendererReference.Color = someNewColor;
```To swap the color
spriteRendererReference.Color = Color.Lerp(firstColor, secondColor, progress01);
``` to lerp the color
you can either lerp it over time in update or make a coroutine which would be cleaner and better to understand
private IEnumerator LerpSpriteColor(Color start, Color end, float lerpTime)
{
for (float t = 0; t < lerpTime; t += Time.deltaTime)
{
float progress = t / lerpTime;
spriteRendererReference.Color = Color.Lerp(start, end, progress);
yield return null;
}
spriteRendererReference.Color = end;
}
Which can be called and stored like this:
Coroutine coroutine = StartCoroutine(LerpSpriteColor(Color.white, Color.black, 0.5f));
The start Color can be always your current Color (in case you have to stop the coroutine early StopCoroutine(coroutine) and start a new one), and the end Color can be the one you want to lerp into based on the current situation.
Oh I see, so the lerp essentially transitions the color into a slow fade. Thanks! I'll try this out and report back 
lerping is basically
c = a + (b - a) * p
it returns a transitioning into b by p% where p is in range [0 ; 1] (where 0 is a, 1 is b and 0.5 is the midpoint between a and b)
Also in this case it's just a linear lerp, you can always apply some fancy functions to get a fancy looking progress (easiest example is ease-in/ease-out which basically transforms linear arguments into non-linear return values)
thanks!
Does this make it 'blink'? So where it goes from color A to B then back to color C in a routine of sorts.
it just goes from A to B and stops at B, unless interrupted (then it stops somewhere in the middle)
I see, to make it return to A would I have to reset the time to 0 after it hits B?
Same as if I had a position A(0 , 0) and B(0 , 1) and wanted to lerp it during 1 second
If I interrupted it after 0.7 seconds it would just stop at (0, 0.7) and stay there
If you want it to return to A then simply just reset the field back to A immediately when you want
or make another lerp back to A
I see, so I would just copy the previous lerp from A to B but make it go from B to A
the time in the coroutine is just how long it should take (t is how much time already elapsed)
Just start another coroutine after the first one ends
I see
also
if you want to lerp again, after A-B to B-A ten you can just make another coroutine which does both of them one after another
so would that mean endless coroutines or do i make a while loop?
like while InRange
loop the coroutine endlessly?
private IEnumerator Lerp_AB_BA_Color(Color A, Color B, float timeAB, float timeBA)
{
yield return LerpSpriteColor(A, B, timeAB);
yield return LerpSpriteColor(B, A, timeBA);
}
No need for endless coroutine, just start it when needed
a coroutine is like an update function
i see
but is stops when you tell it to stop and continues next frame / time period
and after reaching the end it won't run anymore
so in this case it needs to stop when the player is out of range
return means going back to the start of the code right?
and executing it again
yield return stuff
is the way a coroutine says "wait until this thing ends"
yield return null
basically waits for nothing, so it continues the next frame
i see
int i = 0;
yield return new WaitForSeconds(seconds);
Debug.Log(i); // Will print 0 after 'seconds' seconds
i see
The lerping function I wrote earlier basically waits for one frame, same as the update loop does, so it just changes the color over time and then stops
without yield return null it wouldn't stop at all and just run all the loops at once, resulting in an instant transition from one color to another
I see
how do i write color?
I did it like this but its not really working. RGB format
So in this case it calls the color lerping from A to B, and as soon as it reaches B it calls the color lerping for B to A
private IEnumerator LerpSpriteColor(Color start, Color end, float lerpTime) { for (float t = 0; t < lerpTime; t += Time.deltaTime) { float progress = t / lerpTime; (71,82,69).Color = Color.Lerp(start, end, progress); yield return null; }
if you're using Color, then you need values in range [0 ; 1]
just do new Color(r / 255, g / 255, b / 255); to set a color
that's not the way you set the color
(71,82,69).Color isn't a valid thing
i see
if you want to change the color of the sprite then you have to reference the renderer in the inspector and use it's Color field
I think this is a preferable method
[SerializeField] private SpriteRenderer _spriteRenderer; // To be set in inspector
and then just
_spriteRenderer.Color = the_color_you_want;
ahhhh
so to set color i use this method
this is just to create a new Color variable (also it's a constructor, not a method)
you could probably do stuff like idk
private Color _baseColor = new Color(1, 1, 1);
private Color _blackColor = new Color(0, 0, 0);
private const float TRANSITION_TIME = 0.5f;
private Coroutine _coroutine;
// ... somewhere in the code ...
_coroutine = StartCoroutine(LerpSpriteColor(_baseColor, _blackColor, TRANSITION_TIME));
you can replace the base/black color with anything you want using this
this constructor basically expects values in range [0 ; 1] so if you have RGB values in range [0 ; 255] then you'd have to "transform" them into the 01 range by just dividing the values by 255
Argument 1: cannot convert from 'double' to 'float'RoslynCS1503
private Color endColor = new Color(0.2, 0.2, 0.2);
This line seems to assume its a double
You have to add f after the number to tell it that it's a float value
OH
private Color endColor = new Color(0.2f, 0.2f, 0.2f);
I am so stupid
you can also write a _coroutine = null; at the end of your coroutines if you store them
since if one coroutine ends and your code tries to "stop" it before starting a new one, then bad things could happen
and with null it just ignores it
at least I think so
store them?
yeah
You can store a coroutine 'instance' so that you can later interrupt it
Coroutine _coroutine = StartCoroutine(MyCoroutine());
...
StopCoroutine(_coroutine);
_coroutine = StartCoroutine(NewCoroutine());
i see
Same as storing a GameObject
if it's already destroyed and try to Destroy it again then your computer explodes
ahhh okay i might have to store it because i need to stop the blinking once the pc moves away from the collider
This ^
``using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Ebuttonblink : MonoBehaviour
{
[Header("Visual Cue E")]
[SerializeField] GameObject visualCueE;
[SerializeField] private SpriteRenderer spriteRendererE;
bool playerInRange;
bool tristanIsCrouching = false;
private Color baseColor = new Color(1, 1, 1);
private Color endColor = new Color(0.2f, 0.2f, 0.2f);
private const float transitionTime = 0.5f;
private Coroutine coroutineE;
void Awake()
{
playerInRange = false;
visualCueE.SetActive(false);
}
void OnTriggerEnter2D(Collider2D collider)
{
if (collider.gameObject.tag == "Player")
playerInRange = true;
}
void Update()
{
if (playerInRange)
visualCueE.SetActive(true);
if (Input.GetKeyDown("E"))
tristanIsCrouching = true;
else
visualCueE.SetActive(false);
Debug.Log("Tristan is crouching" + tristanIsCrouching);
void OnTriggerExit2D(Collider2D collider)
{
playerInRange = false;
}
}
IEnumerator BlinkButtonE()
{
coroutine(baseColor, endColor, transitionTime, transitionTime);
{
yield return LerpSpriteColor(baseColor, endColor, transitionTime);
yield return LerpSpriteColor(endColor, baseColor, transitionTime);
}
yield return new WaitForSeconds(1f);
}
}
``
Here's what I got
I'm not sure how to assign values to coroutine and LerpSpriteColor
private IEnumerator LerpSpriteColor(Color start, Color end, float lerpTime)
{
for (float t = 0; t < lerpTime; t += Time.deltaTime)
{
float progress = t / lerpTime;
spriteRendererReference.Color = Color.Lerp(start, end, progress);
yield return null;
}
spriteRendererReference.Color = end;
}
private IEnumerator BlinkOnce(Color A, Color B, float timeAB, float timeBA)
{
yield return LerpSpriteColor(A, B, timeAB);
yield return LerpSpriteColor(B, A, timeBA);
}
private IEnumerator BlinkForEternity(Color A, Color B, float timeAB, float timeBA)
{
while (true) yield return BlinkOnce(A, B, timeAB, timeBA);
}
...
Coroutine coroutine = StartCoroutine(BlinkForEternity(A,B,T1,T2));
...
// out of reach
StopCoroutine(coroutine);
coroutine = StartCoroutine(LerpSpriteColor(currentColor, baseColor, T3));
use
```cs
code here
```
Ohhh
also here's an example of how to use it
I'm sorry I'm kind of confused , what does it do here?
I understand the first block, but the blinkonce part is a little confusing for me
They seem to be doing the same thing, all 3 paragraphs, unless I'm wrong
the blink once part
first lerps the color from A to B
then from B to A
and stops
LerpSpriteColor only lerps from A to B
BlinkForEternity infinitely calls the BlinkOnce coroutine as soon as the previous one ends resulting in: A-B B-A, A-B B-A, ...
No
As I said
the first one only goes from A to B
the second one uses the first one twice to go from A to B to A
and the third one uses the second one to go from A to B to A over and over again
if I used the first one with the arguments (black, white, 1) it would go from black to white over the time of 1 second and stop at white
if I used the second one with arguments (black, white, 1, 2) it would go from black to white over the time of 1 second and then from white to black over the time of 2 seconds
and if I used the third one it would do the second one but over and over again
Ahhhhh
Basically using already existing small do-one-thing coroutines to make bigger do-several-things coroutines
what do i do when the program keeps printing
The name 'LerpSpriteColor' does not exist in the current contextRoslynCS0103```
I dont know what value to assign this, the original color?
it means that it doesn't recognise the coroutine you want to use in the place you want to use it
show code
oki
using System.Collections.Generic;
using UnityEngine;
public class Ebuttonblink : MonoBehaviour
{
[Header("Visual Cue E")]
[SerializeField] GameObject visualCueE;
[SerializeField] private SpriteRenderer spriteRendererE;
bool playerInRange;
bool tristanIsCrouching = false;
private Color baseColor = new Color(1, 1, 1);
private Color endColor = new Color(0.2f, 0.2f, 0.2f);
private const float transitionTime = 0.5f;
private Coroutine coroutineE;
void Awake()
{
playerInRange = false;
visualCueE.SetActive(false);
}
void OnTriggerEnter2D(Collider2D collider)
{
if (collider.gameObject.tag == "Player")
playerInRange = true;
}
void Update()
{
if (playerInRange)
visualCueE.SetActive(true);
if (Input.GetKeyDown("E"))
tristanIsCrouching = true;
else
visualCueE.SetActive(false);
Debug.Log("Tristan is crouching" + tristanIsCrouching);
void OnTriggerExit2D(Collider2D collider)
{
playerInRange = false;
}
}
{
for (float t = 0; t < lerpTime; t += Time.deltaTime)
{
float progress = t / lerpTime;
spriteRendererReference.Color = Color.Lerp(start, end, progress);
yield return null;
}
spriteRendererReference.Color = end;
}
private IEnumerator BlinkOnce(Color A, Color B, float timeAB, float timeBA)
{
yield return LerpSpriteColor(A, B, timeAB);
yield return LerpSpriteColor(B, A, timeBA);
}
private IEnumerator BlinkForEternity(Color A, Color B, float timeAB, float timeBA)
{
while (true) yield return BlinkOnce(A, B, timeAB, timeBA);
}
Coroutine coroutine = StartCoroutine(BlinkForEternity(A, B, T1, T2));
StopCoroutine(coroutine);
coroutine = StartCoroutine(LerpSpriteColor(currentColor, baseColor, T3));
}
but format it using
```cs
int i = 0;
```
since it's hard to read
oh i ran out of discord space, ill use pastebin next time
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Ebuttonblink : MonoBehaviour
{
[Header("Visual Cue E")]
[SerializeField] GameObject visualCueE;
[SerializeField] private SpriteRenderer spriteRendererE;
bool playerInRange;
bool tristanIsCrouching = false;
private Color baseColor = new Color(1, 1, 1);
private Color endColor = new Color(0.2f, 0.2f, 0.2f);
private const float transitionTime = 0.5f;
private Coroutine coroutineE;
void Awake()
{
playerInRange = false;
visualCueE.SetActive(false);
}
void OnTriggerEnter2D(Collider2D collider)
{
if (collider.gameObject.tag == "Player")
playerInRange = true;
}
void Update()
{
if (playerInRange)
visualCueE.SetActive(true);
if (Input.GetKeyDown("E"))
tristanIsCrouching = true;
else
visualCueE.SetActive(false);
Debug.Log("Tristan is crouching" + tristanIsCrouching);
void OnTriggerExit2D(Collider2D collider)
{
playerInRange = false;
}
}
private IEnumerator LerpSpriteColor(Color start, Color end, float lerpTime)
{
for (float t = 0; t < lerpTime; t += Time.deltaTime)
{
float progress = t / lerpTime;
spriteRendererReference.Color = Color.Lerp(start, end, progress);
yield return null;
}
spriteRendererReference.Color = end;
}
private IEnumerator BlinkOnce(Color A, Color B, float timeAB, float timeBA)
{
yield return LerpSpriteColor(A, B, timeAB);
yield return LerpSpriteColor(B, A, timeBA);
}
private IEnumerator BlinkForEternity(Color A, Color B, float timeAB, float timeBA)
{
while (true) yield return BlinkOnce(A, B, timeAB, timeBA);
}
Coroutine coroutine = StartCoroutine(BlinkForEternity(A, B, T1, T2));
StopCoroutine(coroutine);
coroutine = StartCoroutine(LerpSpriteColor(currentColor, baseColor, T3));
}
Ok, dear god
first of all, you have your OnTriggerExit2D inside Update
second of all, don't just copy paste, it obviously won't work, I just provided examples
last three lines should just go away
should it not be inside update? ive done it that way for most stuff
no
damn, TIL
if it's inside another method then it's considered to be a local method, only existing within that one method
oh
OnTriggerEnter2D has to be available straight from within your class in order to call it
i see
basically take it outside of update please
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Ebuttonblink : MonoBehaviour
{
[Header("Visual Cue E")]
[SerializeField] GameObject visualCueE;
[SerializeField] private SpriteRenderer spriteRendererE;
bool playerInRange;
bool tristanIsCrouching = false;
private Color baseColor = new Color(1, 1, 1);
private Color endColor = new Color(0.2f, 0.2f, 0.2f);
private const float transitionTime = 0.5f;
private Coroutine coroutineE;
void Awake()
{
playerInRange = false;
visualCueE.SetActive(false);
}
void OnTriggerEnter2D(Collider2D collider)
{
if (collider.gameObject.tag == "Player")
playerInRange = true;
}
void OnTriggerExit2D(Collider2D collider)
{
if (collider.gameObject.tag == "Player")
playerInRange = false;
}
void Update()
{
if (playerInRange)
visualCueE.SetActive(true);
if (Input.GetKeyDown("E"))
tristanIsCrouching = true;
else
visualCueE.SetActive(false);
Debug.Log("Tristan is crouching " + tristanIsCrouching);
}
Like this basically
keep it clean.
I did that thanks!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Ebuttonblink : MonoBehaviour
{
[Header("Visual Cue E")]
[SerializeField] GameObject visualCueE;
[SerializeField] private SpriteRenderer spriteRendererE;
bool playerInRange;
bool tristanIsCrouching = false;
private Color baseColor = new Color(1, 1, 1);
private Color endColor = new Color(0.2f, 0.2f, 0.2f);
private const float transitionTime = 0.5f;
private Coroutine coroutineE;
void Awake()
{
playerInRange = false;
visualCueE.SetActive(false);
}
void OnTriggerEnter2D(Collider2D collider)
{
if (collider.gameObject.tag == "Player")
playerInRange = true;
}
void OnTriggerExit2D(Collider2D collider)
{
if (collider.gameObject.tag == "Player")
playerInRange = false;
}
void Update()
{
if (playerInRange)
visualCueE.SetActive(true);
if (Input.GetKeyDown("E"))
tristanIsCrouching = true;
else
visualCueE.SetActive(false);
Debug.Log("Tristan is crouching " + tristanIsCrouching);
}
private IEnumerator LerpSpriteColor(Color A, Color B, float lerpTime)
{
for (float t = 0; t < lerpTime; t += Time.deltaTime)
{
float p = t / lerpTime;
spriteRendererE.Color = Color.Lerp(A, B, p);
yield return null;
}
spriteRendererE.Color = end;
}
private IEnumerator BlinkOnce(Color A, Color B, float timeAB, float timeBA)
{
yield return LerpSpriteColor(A, B, timeAB);
yield return LerpSpriteColor(B, A, timeBA);
}
private IEnumerator BlinkForEternity(Color A, Color B, float timeAB, float timeBA)
{
while (true) yield return BlinkOnce(A, B, timeAB, timeBA);
}
That should be your whole code (except for calling the coroutines)
ah, not exactly
now it's good
Also, if you want it to be easier and not store the coroutine at all
you can just use the method StopAllCoroutines() and simply start the coroutines using StartCoroutine(MyCoroutine(params)); without the need to store it in your coroutineE
i see
'SpriteRenderer' does not contain a definition for 'Color' and no accessible extension method 'Color' accepting a first argument of type 'SpriteRenderer' could be found (are you missing a using directive or an assembly reference?)RoslynCS1061
The name 'end' does not exist in the current contextRoslynCS0103
Got these 2 problems, how should I label spriterenderer?
oh, my bad
it's not a Color field, it's named "color"
small letter
renderer.color = ...
as for the second one I forgot to rename it, should be B instead of end
AH
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Ebuttonblink : MonoBehaviour
{
[Header("Visual Cue E")]
[SerializeField] GameObject visualCueE;
[SerializeField] private SpriteRenderer spriteRendererE;
bool playerInRange;
bool tristanIsCrouching = false;
private Color baseColor = new Color(1, 1, 1);
private Color endColor = new Color(0.2f, 0.2f, 0.2f);
private const float transitionTime = 0.5f;
private Coroutine coroutineE;
void Awake()
{
playerInRange = false;
visualCueE.SetActive(false);
}
void OnTriggerEnter2D(Collider2D collider)
{
if (collider.gameObject.tag == "Player")
playerInRange = true;
}
void OnTriggerExit2D(Collider2D collider)
{
if (collider.gameObject.tag == "Player")
playerInRange = false;
}
void Update()
{
if (playerInRange)
visualCueE.SetActive(true);
if (Input.GetKeyDown("E"))
tristanIsCrouching = true;
else
visualCueE.SetActive(false);
Debug.Log("Tristan is crouching " + tristanIsCrouching);
}
private IEnumerator LerpSpriteColor(Color A, Color B, float lerpTime)
{
for (float t = 0; t < lerpTime; t += Time.deltaTime)
{
float p = t / lerpTime;
spriteRendererE.color = Color.Lerp(A, B, p);
yield return null;
}
spriteRendererE.color = B;
}
private IEnumerator BlinkOnce(Color A, Color B, float timeAB, float timeBA)
{
yield return LerpSpriteColor(A, B, timeAB);
yield return LerpSpriteColor(B, A, timeBA);
}
private IEnumerator BlinkForEternity(Color A, Color B, float timeAB, float timeBA)
{
while (true) yield return BlinkOnce(A, B, timeAB, timeBA);
}
Also I believe there is no need for half of your update method
you don't need to check if he's in range and then activate it, just do it within OnTriggerEnter2D
I see
ahh
OnTriggerExit2D can handle it
I'm curious, why is it that we use an IEnum here, not a foreach loop to Lerp
IEnumerator coroutime does thing across time
you use foreach if you have an array or a list of elements
that's not a case here
you don't loop through any different variables
you just want to delay the transition by using time
I see
So because they're not a type of variables or elements, and the code is just trying to lerp from A to B
an IEnum is used
yeah
Last couple things, just to clarify, yield return null is used when you want the code to continue at the next frame without waiting
While yield return WaitForSeconds(x) means the game should wait for x seconds before displaying/executing the next line of code?
yield return new WaitForSeconds(x);
And yes
i see
Ok on Debug the E button doesn't appear above the character's head or blink.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Ebuttonblink : MonoBehaviour
{
[Header("Visual Cue E")]
[SerializeField] GameObject visualCueE;
[SerializeField] private SpriteRenderer spriteRendererE;
bool playerInRange;
bool tristanIsCrouching = false;
Color A = new Color(1, 1, 1);
Color B = new Color(0.2f, 0.2f, 0.2f);
const float transitionTime = 0.5f;
Coroutine coroutineE;
float lerpTime = 2f;
void Awake()
{
playerInRange = false;
visualCueE.SetActive(false);
}
void OnTriggerEnter2D(Collider2D collider)
{
if (collider.gameObject.tag == "Player")
playerInRange = true;
}
void OnTriggerExit2D(Collider2D collider)
{
playerInRange = false;
}
void Update()
{
//if (playerInRange)
//visualCueE.SetActive(true);
if (Input.GetKeyDown("e"))
tristanIsCrouching = true;
//else
//visualCueE.SetActive(false);
Debug.Log("Tristan is crouching " + tristanIsCrouching);
}
private IEnumerator LerpSpriteColor(Color A, Color B, float lerpTime)
{
for (float t = 0; t < lerpTime; t += Time.deltaTime)
{
float p = t / lerpTime;
spriteRendererE.color = Color.Lerp(A, B, p);
yield return null;
}
spriteRendererE.color = B;
}
private IEnumerator BlinkOnce(Color A, Color B, float timeAB, float timeBA)
{
yield return LerpSpriteColor(A, B, timeAB);
yield return LerpSpriteColor(B, A, timeBA);
}
private IEnumerator BlinkForEternity(Color A, Color B, float timeAB, float timeBA)
{
while (true) yield return BlinkOnce(A, B, timeAB, timeBA);
}
}```
You didn't set it to active anywhere
write visualCueE.SetActive(true); inside OnTriggerEnter2D when the tag is correct
also instead of writing collider.gameObject.tag == "Player"
I'd be better if you did collider.CompareTag("Player")
and if you don't want to check for the tag at all, then just go into physics2d setting in your project settings and deactivate all collisions between your Ebuttonblink layer leaving just the player layer (that is, if they have different unique layers), so if OnTriggerEnter2D is ever called then it's 100% the player
shorter and easier to understand
I see
Will that cause issues in future?
As long as you know what you're doing, no
But for now you can just keep the tag check
Well I am still new to this so I'm afraid I'll mess up in future if other collisions are needed
So stick to tag checking for now
Oki
But it becomes useful once there are a lot of different things an object can collide with
Because you never start the coroutine.
just write StartCoroutine(BlinkForEternity(A, B, transitionTime, transitionTime)); inside OnTriggerEnter2D and StopAllCoroutines() within OnTriggerExit2D if the tag is correct
ohhhh
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Ebuttonblink : MonoBehaviour
{
[Header("Visual Cue E")]
[SerializeField] GameObject visualCueE;
[SerializeField] private SpriteRenderer spriteRendererE;
bool playerInRange;
bool tristanIsCrouching = false;
Color A = new Color(0.4f, 0.5f, 0.3f);
Color B = new Color(0.2f, 0.2f, 0.2f);
const float transitionTime = 0.5f;
Coroutine coroutineE;
float lerpTime = 2f;
void Awake()
{
playerInRange = false;
visualCueE.SetActive(false);
}
void OnTriggerEnter2D(Collider2D collider)
{
visualCueE.SetActive(true);
if (collider.CompareTag("Player"))
playerInRange = true;
StartCoroutine(BlinkForEternity(A, B, transitionTime, transitionTime));
}
void OnTriggerExit2D(Collider2D collider)
{
playerInRange = false;
StopAllCoroutines();
}
void Update()
{
//if (playerInRange)
//visualCueE.SetActive(true);
if (Input.GetKeyDown("e"))
tristanIsCrouching = true;
//else
//visualCueE.SetActive(false);
Debug.Log("Tristan is crouching " + tristanIsCrouching);
}
private IEnumerator LerpSpriteColor(Color A, Color B, float lerpTime)
{
for (float t = 0; t < lerpTime; t += Time.deltaTime)
{
float p = t / lerpTime;
spriteRendererE.color = Color.Lerp(A, B, p);
yield return null;
}
spriteRendererE.color = B;
}
private IEnumerator BlinkOnce(Color A, Color B, float timeAB, float timeBA)
{
yield return LerpSpriteColor(A, B, timeAB);
yield return LerpSpriteColor(B, A, timeBA);
}
private IEnumerator BlinkForEternity(Color A, Color B, float timeAB, float timeBA)
{
while (true) yield return BlinkOnce(A, B, timeAB, timeBA);
}
}
Still no blink
StartCoroutine(BlinkForEternity(A, B, transitionTime, transitionTime));```
Should this be placed outside the if(collider.CompareTag)?
void OnTriggerEnter2D(Collider2D collider)
{
if (collider.CompareTag("Player"))
{
visualCueE.SetActive(true);
playerInRange = true;
StartCoroutine(BlinkForEternity(A, B, transitionTime, transitionTime));
}
}
void OnTriggerExit2D(Collider2D collider)
{
if (collider.CompareTag("Player"))
{
visualCueE.SetActive(false);
playerInRange = false;
StopAllCoroutines();
}
}```
Also, check if it even runs the method
but if the button appears then it should be ok
np
Also check out some C# tutorials, even the basic ones
Since I saw you struggle with a few stuff here
oki!
Might be good to learn all the basics for smoother future unity learning process
I am ok with basic C# but coroutines and ienums make me confused
polymorphoisms too, those things I think I need to study more
Don't worry, you'll get used to these
Better be scared of multithreading
(I still have to force myself to start learning this)
And polymorphism isn't that bad either, it's just a bunch of "base" classes which basically exist to specify some methods to be overriden by other classes so that you can store different class instances by using their base class, and still be able to call their unique methods with custom behaviour
public abstract class MoveBase : MonoBehaviour
{
public virtual void UpdatePosition() {}
}
public class EnemyMove : MoveBase
{
public override void UpdatePosition() { custom behaviour... }
}
...
MoveBase[] moveArray = new MoveBase[10];
moveArray[0] = some_EnemyMove_instance;
moveArray[0].UpdatePosition(); // goes through MoveBase to EnemyMove and calls the custom behaviouir
Also it might be better to just an interface in this scenario, depends on the situation
I see I heard they're never used when compared to interfaces
I believe that an interface is best to use when you just want to implement different behaviours for the same 'type' of object, for example weapons
As for polymorphism, I don't really know
Haven't been using it that much
I, so like Interfaces are just stuff you can assign to, and call later?
So I can assign IDamagable to a car, house and person and when I throw a bomb I can just called the IDamagable instead of tagging every single object
Interface basically demands you to implement the same methods and fields that it also has, but with your own behaviour to it
So you can call for example an IDamagable method from any given object, be it car, door, neighbours cat
Without having to reference different scripts such as Car, Door or Cat
I see, Interfaces are usually empty right? So They just get called when needed
You define what an interface contains, as well as you call any method or property from that interface when needed
easiest example would be
for example
OnTriggerEnter2D
collider.CompareTag("Damagable")
Yeah
if yes then
collider.gameObject.GetComponent<IDamagable>().DealDamage(1);
or something like that, depends on how you do things
it will call the customly implemented DealDamage(int damage) method within any script that implemented it
Ah, so everything from <IDamagable> contains all methods boxed into IDamagable interface
for example
public interface IDamagable
{
private int _health { get; set; }
public void DealDamage() {}
}
public class Cat : MonoBehaviour, IDamagable // Will throw error until implemented
{
private int _health { get; set; } = 7;
public void DealDamage() { --_health; }
}
public class Dog : MonoBehaviour, IDamagable
{
private int _health { get; set; } = 3;
public void DealDamage() { _health -= 2; }
}
Ahhh so it kinda makes you inherit all methods from the interface
I see
and an interface basically reminds you to implement them from zero
From zero?
Meaning that there isn't any base inherited method
you just have to implement your own following the "instruction provided by the interface"
I see
Like using MonoBehaviour (class) makes you inherit all it's members, an IDamagable (interface) makes you create them by yourself, no inheritance
So no variables to be inherited, just the empty methods
or do we not even inherit those empty methods and have to make them oursevles, so the Interface is essentially a fancy tagging system?
Nothing from the interface will be inherited, you basically have to copy everything from the interface and then maybe add your custom behaviour to the properties/methods
It just ensures that this method/property exists, it doesn't care what it does, it just has to be callable
I'd call it "inheritance" but with extra steps and safety, lol
You do call it however you want
The main idea is that is just ensures the creation of certain methods and properties
I see
ensures the creation of certain methods and properties
So like... what does this mean in layman terms?
I don't really understand this
You code won't compile if you don't create the methods and properties that it wants. That's all there is to it
It just forces you to include them in your script somewhere (so it's callable via the interface)
Ohhhhh
But some tutorials on interfaces would probably explain it better than me lol