#archived-code-general
1 messages · Page 212 of 1
? won't work in this case because you are trying to get a nullable component by adding it
good to know thanks
Its easy enough in my case because I only need to grab it in 1 case where it wont be null anyway
if(attackType == AttackType.sniper)
{
laser = fighter.GetComponent<LookAtEnemy>().laser.gameObject;
}
there are two main patterns I usually use for this
- If component NEEDS to be there
x = GetComponent, then Debug.Assert( x!= null, “Couldn’t find component!”);
- If component is optional,
if ( TryGetComponent( out x))
so you have separate logic for if you can and can’t find the component
totally forgot TryGetComponent existed
trygetcomponent is a bit lighter if false because you don’t need to get something for the out parameter
but those are the two main patterns I always use
Get and assert, or if tryget
I'm trying to detect if two line renderers overlap. Due to the data I'm parsing into a line renderer, it's possible that the data I'm getting could cause two identical lines to be drawn. Is there a better way to do this than to loop through all the points of a line renderer against all of the points in another line renderer, and seeing if they match?
Oh, I should also note: The lines I'm drawing might be identical, but in a different order. They're closed polygons so the starting point could be anywhere in the shape, so I can't just compare index 0 to 0 and so on
maybe sort the points then compare?
sort by x then tiebreak with y for example?
That could work. It'd at least reduce the worst case comparison
I'm not sure if the time cost of the sorting outweighs the extra time spent checking unnecessary nodes though...
Wait are we looking for an overlap? or for identical drawings?
and actually sorting the points doesn't quite work for identical drawing detection because you can draw many different pictures with the same points by changing which points connect to which other points 🤔
it's more the edges/lines you'd have to sort and compare
So are you only trying to detect when two line renderers have the same points and draw the same shape?
i.e. they have the points in the same order, modulo a circular shift
0123 and 1230 are a match
So, basically, I have polygons defined by a list of points in a file generated by another program. I'm consuming that output and making shapes with it. The shapes are closed polygons, but the output could contain multiple overlapping shapes. They'd have all the same points, but whichever one is the "start" might be different. Imagine two squares, one of them is (1, 0), (1, 1), (0, 1), (0, 0) and the other is (0, 1), (0, 0), (1, 0), (1, 1). They're the same square, so I don't want two line renderers drawing it
I see it the other way around 😉
Ok so you just don't want to draw the same shape twice - like what Fen mentioned
Yeah
three scans+hash table
So maybe what you can do is find the minimum point and rearrange the list such that the minimum point is first. (e.g. the one with the smallest x then smallest y as tiebreak).
So:
(1, 0), (1, 1), (0, 1), (0, 0)
Becomes
(0, 0), (1, 0), (1, 1), (0, 1) because (0,0) is the "smallest" point
then you can compare the shapes point by point to see if they're identical
you basically slice at the small point and reconnect the two sublists
Does that actually save any time over just iterating over both lists?
you still have to iterate
idk why the first thing comes to my mind is binary search, until i realize that O(n) is must since you have to check if all the points are same and ordered
You will have to iterate over each list at least once in every case
There are fastish ways to tell that they are definitely NOT the same shape
how many times you gonna ask this
e.g.:
- different number of points
- HashSet.IntersectWith the other set is the same as the set.
That is kind of an off-topic question. Especially with how many times you've asked it
Crossposting this
#archived-code-general message
Is also off-topic
Well 🤷♂️ find a server with a channel you can do that in. Cause this one aint that
What is difference with
Debug.Log("Value: " + value);
and
Debug.Log($"Value: {value}"); ?
Two different ways to achieve the same thing. The bottom one is basically equivalent to:
Debug.Log(string.Format("Value: %s", value));```
it's just more convenient usually to write things inline like that
imagine:
string s = "I have " + apples " apples and " + bananas + " bananas";```
Compared to:
```cs
string s = $"I have {apples} apples and {bananas} bananas";```
The latter is called "string interpolation".
it's just much cleaner / easier to read
It does require you to know exactly what the format string will look like at compile time, though
Probably not an issue for you, though
Where would string interpolation be an issue?
Thank you this makes sense!
it's not an "issue", it's just a technique to make templating strings that include dynamic information more simple for the programmer
pretty sure it's faster than the repeated + concatenation too when there are multiple dynamic bits of information
Yeah that makes sense, thanks all!
hi I wrote this script to smoothly interchange the positions of two gameObjects
{
cachedPositions.Add(flipModel, flipModel.transform.position); // add first cached pos
cachedPositions.Add(foldModel, foldModel.transform.position); // add second cached pos
currentObject = this.gameObject; // get ref to current obj
}
private GameObject GetActiveClicked() // returns the active model not too difficult
{
if (flipModel.Equals(currentObject))
{
return flipModel;
}
else
{
return foldModel;
}
}
private IEnumerator MovePositions(float duration)
{ float elapsedTime = 0f;
Vector3 temp = cachedPositions[GetActiveClicked()]; // retrieve the active clicked
if (flipModel.Equals(GetActiveClicked()))
{
cachedPositions[GetActiveClicked()] = foldModel.transform.position; // swap the positions
foldModel.transform.position = temp;
}
else
{
cachedPositions[GetActiveClicked()] = flipModel.transform.position;
flipModel.transform.position = temp; // swap them
}
while(elapsedTime < duration)
{
Vector3.MoveTowards(flipModel.transform.position, cachedPositions[flipModel], animationCurve.Evaluate(elapsedTime/duration));
Vector3.MoveTowards(foldModel.transform.position, cachedPositions[foldModel], animationCurve.Evaluate(elapsedTime/duration));
elapsedTime += Time.deltaTime;
yield return null; // check why not moving
}
}
public void OnPointerClick(PointerEventData data)
{
StartCoroutine(MovePositions(10f)); // does the time matter
}```
where cachedPositions is a dictionary
it's not swapping and responding instantenously but only one item is moving
This code doesn't do anything:
Vector3.MoveTowards(flipModel.transform.position, cachedPositions[flipModel], animationCurve.Evaluate(elapsedTime/duration));
Vector3.MoveTowards(foldModel.transform.position, cachedPositions[foldModel], animationCurve.Evaluate(elapsedTime/duration)); ```
you're calculating a new position and just discarding it
you would need to do something like:
flipModel.transform.position = Vector3.MoveTowards(flipModel.transform.position, cachedPositions[flipModel], animationCurve.Evaluate(elapsedTime/duration));
See how in this case we're actually assigning a new position to the object?
yes i didnt notice that let me now try this
ok now it moves one of them moves to whether the other is and stays with it
as it moves to the position the other was
I used the dictionary to hopefully avoid this issue but idk why it is not working
well you're immediately doing this at the start of the coroutine:
if (flipModel.Equals(GetActiveClicked()))
{
cachedPositions[GetActiveClicked()] = foldModel.transform.position; // swap the positions
foldModel.transform.position = temp;
}
else
{
cachedPositions[GetActiveClicked()] = flipModel.transform.position;
flipModel.transform.position = temp; // swap them
}```
and I'm not sure why exactly
I also don't get why it matters which one you clicked. Shouldn't they both be moving in any case?
Shouldn't this just be:
cachedPositions[foldModel] = flipModel.transform.position;
cachedPositions[flipModel] = foldModel.transform.position;``` without any if/else and without moving anything right away?
yeah I mean both are moving at the same time all I wanted to do have a way of keeping track of which one is moving where
yes this does that
yes so you're right and there is no need for the if else
just move it to the position of the other one
Also the way you're using the animation curve is quite weird
yeah I am very unfamiliar with working with them so I took a random guess
and tried to compress it bu duration
shouldn't it be:
float t = elapsedTime / duration;
t = animationCurve.Evaluate(t);
flipModel.transform.position = Vector3.Lerp(cachedPositions[foldModel], cachedPositions[flipModel], t);
foldModel.transform.position = Vector3.Lerp(cachedPositions[flipModel], cachedPositions[foldModel], t);```
Each phone should be responsible to move itself and knowing where to move to
so @somber tapir separate script attached to each phone?
ehhh
that sounds way more complicated
well not way, but definitely more complicated
yeah it sounds more complicated @leaden ice i'll give what you put a try
it works but does an immediate swap
and then does the animation
t = animationCurve.Evaluate(t);
flipModel.transform.position = Vector3.Lerp(cachedPositions[foldModel], cachedPositions[flipModel], t);
foldModel.transform.position = Vector3.Lerp(cachedPositions[flipModel], cachedPositions[foldModel], t);```
basically what @leaden ice wrote
you need to swap the values inside the lerp
first the current position, then the target position
ok yes now how could I continuously keep interchanging them now
thats where I wanted to swap the values after the lerp using the dictionary?
so that the next time someone clicks on the phone it swaps the other way
I think the hardcoding of the two objects here and the dictionary as well are overkill and kind of getting in your way
{
float elapsedTime = 0f;
while(elapsedTime < duration)
{
float t = elapsedTime / duration;
t = animationCurve.Evaluate(t); // evaulate at the animation ccurve
flipModel.transform.position = Vector3.Lerp(cachedPositions[flipModel], cachedPositions[foldModel], t); // LERP TO POS1
foldModel.transform.position = Vector3.Lerp(cachedPositions[foldModel], cachedPositions[flipModel], t); // LERP TO POS2
elapsedTime += Time.deltaTime; // increment the time
yield return null;
}
cachedPositions[flipModel] = flipModel.transform.position; // store position back into dict
cachedPositions[foldModel] = foldModel.transform.position;
}
this works you have to update the positions in the dictionary after
now my question would be this is a straight path to the other object could I make a curve trajectory path where one phone swings around the other?
You can make this agnostic to the objects themselves.
IEnumerator Swap(float duration, Transform a, Transform b, AnimationCurve curve) {
Vector3 aStart = a.position;
Vector3 bStart = b.position;
float elapsedTime = 0;
while(elapsedTime < duration)
{
float t = elapsedTime / duration;
t = curve.Evaluate(t);
a.position = Vector3.MoveTowards(aStart, bStart, t);
b.position = Vector3.MoveTowards(bStart, aStart, t);
elapsedTime += Time.deltaTime;
yield return null;
}
}```
then you don't need to worry about the dictionary or swapping anything
you can pass any two objects and any curve into this thing and it will swap them according to the curve and their current positions
yes of course but I want to change the actual motion
so that instead of heading straight to the point
it traves along a curved path to the point
like i know parametric equations and that bs
for example if you want to make a bunch of assumptions you could treat t as an angle around a circle and position them along the circle using a parametric equation
i was talking with someone who said I should use two curves to paramterize x and y components of motion
but idk if this is a correct approach
that's an option too
it's not really correct or incorrect, there's a lot of ways to do it.
uhhh... maybe? 😛
It definitely will if you want to make a curve that isn't easily mathematically expressible
dude i dont want to go back to calc IV
or if you don't feel like doing math
lol yeah i already died doing those things in Calc IV
but i mean honestly could be fun
What are some good numbers inside a profiler ?
do you have a specific library recommendation then from Spline?
thank you so much @leaden ice will take a look and have some fun with it
I'm particluarly fond of 5 and 7
I meant more like at what Time ms should I keep stuff
trying to understand waht causes a jolt by profiling but hmm unsure about it
especially since most of my high numbers are from universal render pipeline
It's not really about that. You should decide on a target framerate and try to keep your game under (1000 / framerate)ms per frame
so hard code frame rate into code ?
well its a small mobile game so 30-60 limit
is all I want
and game runs at that smoothly
besides that 1 occasional jolt it sometimes gets and thats my issue 
ok so profile your game on your target hardware and try to make sure you're getting 60fps
Look into that frame and see what the problem is.
this is why Im asking
cuz its universal render pipeline and 2d physics
I dont use any shaders or nothing thats not out of the box
and its just 2d project
isnt editor loop the fact it runs in editor ?
that doesnt exist on play right ?
i mean on build
Ok you should try profiling the game on your target hardware in a build then
Instructions for that if you need are here https://docs.unity3d.com/Manual/profiler-profiling-applications.html scroll down to whatever platform you're building for (I assume Android)
ye its android but ill do it on pc first
same issue occurs across every platform
but ill check it and see how it goes
what confuses me is every tutorial I see has so much GC and so much more Time ms and it runs smoothly

Set the profiler to edit mode if you need to see what specifically is taking long
You might just need to turn on incremental gc. For some reason it was off for me by default
Hello im using Unity Gaming Services with Accountname+Password as Authentification. How can I acess the Username with script ? Where is it saved ?
Thanks I found culprit I think, I disabled the game object that is responsible for what was triggering most in edit mode. Built it across pc/mobile tested and there is no weird spikes. Now I know exactly what to focus in on

could I use Slerp
I dont have access to Splines
my project is in Unity 2019.4 😦
I won't stop you
but would it work lol?
the problem with slerp is that it will take the shortest path along the surface of a sphere
that might or might not be the path you want it to take
especially if your two points are on opposite poles of the sphere, the path is kind of undefined
hmmm yeah but the alternative is using the bezier curve equation is easier than using parametrics
if you imagine travelling from the north pole to the south pole of the earth, all lines of longitude are equally valid and equal distance paths
yes so there's no distinct path
I mean I assume Unity will just pick something but it might not be what you want. You could try to goose it a little by starting from slightly off center
yeah I'll see if I can goof the points a bit
and see if it'll magically give me a correct pat h
path
float elapsedTime = 0f;
while(elapsedTime < duration)
{
float t = elapsedTime / duration;
t = animationCurve.Evaluate(t); // evaulate at the animation ccurve
flipModel.transform.position = Vector3.Slerp(cachedPositions[flipModel], cachedPositions[foldModel] - new Vector3(offsetFloat, 0, 0), t); // LERP TO POS1
foldModel.transform.position = Vector3.Slerp(cachedPositions[foldModel], cachedPositions[flipModel], t); // LERP TO POS2
elapsedTime += Time.deltaTime; // increment the time
yield return null;
}
cachedPositions[flipModel] = flipModel.transform.position; // store position back into dict
cachedPositions[foldModel] = foldModel.transform.position;
}```
im thinking something like this make a vector3 and take some x away from it
@leaden ice THANKS that helped me a lot!
if i do cs PlayerPrefs.Set("email", email); Debug.Log(PlayerPrefs.Get("email")); will this print out the email or do I need to PlayerPrefs.Save() before using Get()? 
thanks 😄
but they are there in memory without a Save
does someone knows why WebResquest works fine inside editor, but have a different return inside a WebGL build? If so I made a tread in the forum so my code and error is there if someone is willing to help
Hello, WEBGL Audio is not working at open. When i click to canvas it's starting to work. I have this issue. I google it but so many people have that problem. Do you have any ideas to solve it?
It's probably the browser suppressing audio.
But I'm not sure, I guess YouTube plays audio without a click
Does anyone know if Unity is responsible for creating these?
Cool, thanks. I might add them to the GitHub gitignore
you guys remember I was talking about a tree structure that was really a graph that's just a bunch of separate trees?
turns out, it's just called a forest
Weirdly I can't find any info about it on unity docs
And only one forum thread
Maybe give it a 👍 if you can
I would probably knock back the PR given the lack of supporting docs
This is very weird. Just to make sure, did you make any changes in project - physics or to the timestep?
no changes since we worked on it togheter
i was making a new movement script cuz i was at a point of throwing the laggy one away and then i enabled interpolation and it started lagging again
even on the new movement script which is very tiny
Together with who? Are you sure the other person didn't change anything in the project settings?
no togheter with you and fen
im the only one with access to the project
Yeah, I mean, before that point.
no changes but the interpolation
Interpolation shouldn't cause lag. In the worst case, it wouldn't do anything. That is with default physics settings
i hopped on, created a new simple movement script and turned on interpolation and it happened again
Yeah, but you didn't answer my question. Did you touch the project - physics settings at any point in the project lifetime?
any point in the project lifetime, this project exists for almost a year now
but nothing of what i know about, i usually dont mess with physics settings
Or maybe they went corrupt at some point. Can you share the settings? As well as the timestep settings(I think it's under project settings - time?)
Yes, those are the default values
Hmm
i believe fen was going to try to recreate it cuz he also found it not making any sense
Yeah, I'll give it a shot later as well. I've never encountered such a behaviour from interpolation and haven't seen anyone that did. Which make me think that it's something unique to your project or is a bug in your unity version.
im using 2022.3.8f1
im tomorrow going to start a new project and test it again to see it it misbehaves in that project aswell
if I define a method/property with =>, will the compiler realize it should probably be inlined?
!code
📃 Large Code Blocks
Use links to services like:
https://gdl.space/, https://paste.ofcode.org/, https://hatebin.com/, https://paste.myst.rs/, https://hastebin.com/
📃 Inline Code
Surround code with three backquotes. Not quotation marks.
To format as C#, add cs to the first line:
```cs
// Your code here
```
Add a comment with a line number if there is an error message.
Yes true but on the documents its saying you cant play audio without user permission. Youtube is another level
ok, I just made my first public git. I put the ForestGraph class I made on it. Open to feedback:
https://github.com/LoupAndSnoop/GenericDataStructures/blob/main/ForestGraph.cs
Is there anyway to see the actually coding for how certain built-in methods work. For example, I'm trying to figure out how to set up custom oblique projection matrices, but I'm having trouble finding it, so I would like to see how the built-in one works to learn from it.
If it's on the c# side https://github.com/Unity-Technologies/UnityCsReference although a lot is through C++ bindings (which is not open source)
Ok, I'll take a look at that thanks.
`
//Forces the player to slide down slopes that are too steep
private void SetSlopeVelocity()
{
if(Physics.Raycast(transform.position, Vector3.down, out RaycastHit hitInfo, 5))
{
float angle = Vector3.Angle(hitInfo.normal, Vector3.up);
Debug.Log("Slope Angle: " + angle);
if (angle >= controller.slopeLimit)
{
slopeSlideVelocity = Vector3.ProjectOnPlane(new Vector3(0, ySpeed, 0), hitInfo.normal);
return;
}
}
slopeSlideVelocity = Vector3.zero;
}
//In update method
if(isSteepSliding)
{
movement = slopeSlideVelocity;
movement.y = ySpeed;
//movement.x += x * moveSpeed / 3;
movement.z += -x * moveSpeed / 3;
}
controller.Move(movement * Time.deltaTime);
}
`
Why do I have to add the the z axis my "x" value, which is the value im getting from Input.GetAxis("Horizontal"); which too my understanding is the x axis, while vertical is the z axis as z is forward and backward and x is left and right? Also why does x have to be negative too? It doesnt make sense it should just be += x and += z???
Why are you asking us? We didn't write that code.😅
idk im just really frusterated... I really want to get this functionality done tonight and its taking forever
Hoped someone would have a tip or somth
Well, if you did write it, then we should ask you as to why would you write it like that.
Well I didnt initially, I only changed it based on testing. It was initally just movement.x += x etc
Your testings are probably incomplete. Try rotating your character and see if it still works.
I already checked that lol, that was my first guess
If I rotate it, the rest of the movement functionality breaks
So you're trying to say that it works correctly with the provided code?
Ok, so it doesn't work correctly.
No, I have the movement in one script atm, walking running, jumping, and in this case what im trying to work out, sliding down a slope thats too steep
However I dont want to take all control from the player, so I want them to be able to move slightly left or right when sliding
I don't think it's a good idea to split movement related code into separate scripts.
Well yeah, I have it in one
Anyways, it's not clear what issue you have or what is the context of it.
Alright, sorry Ill just keep at it, thanks for trying...
Here's how you typically describe an issue:
I want X to happen, but with current code Y happens.
Relevant code:
code
Relevant scene screenshots:
screenshot
Maybe a video too if it's hard to explain with words.
Well if thats the case, I would have worded it like this:
I want the player to be able to slightly adjust their velocity when sliding down a steep slope, the code will replace typical movement with a velocity that points down the slope.
However with current code, "A" and "D" keys makes player move forward and backward, whilst "W" and "S" keys make the player move left and right. While all other movement the player moves correctly given the keys.
Relavent Code:
`
//Forces the player to slide down slopes that are too steep
private void SetSlopeVelocity()
{
if(Physics.Raycast(transform.position, Vector3.down, out RaycastHit hitInfo, 5))
{
float angle = Vector3.Angle(hitInfo.normal, Vector3.up);
if (angle >= controller.slopeLimit)
{
slopeSlideVelocity = Vector3.ProjectOnPlane(new Vector3(0, ySpeed, 0), hitInfo.normal);
return;
}
}
slopeSlideVelocity = Vector3.zero;
}
//Called in update function
if(isSteepSliding)
{
movement = slopeSlideVelocity;
movement.y = ySpeed;
movement.x += x * moveSpeed / 3;
movement.z += z * moveSpeed / 3;
}
controller.Move(movement * Time.deltaTime);
//In InputController
public float GetX()
{
return Input.GetAxis("Horizontal");
}
public float GetZ()
{
return Input.GetAxis("Vertical");
}
`
idk if that makes it any clearer
And all rotations are set to 0, and I have object tools set to global so x should be left and right with z forward and backwards relative to the player
Maybe share the relevant script entirely following the guidelines
!code
📃 Large Code Blocks
Use links to services like:
https://gdl.space/, https://paste.ofcode.org/, https://hatebin.com/, https://paste.myst.rs/, https://hastebin.com/
📃 Inline Code
Surround code with three backquotes. Not quotation marks.
To format as C#, add cs to the first line:
```cs
// Your code here
```
Add a comment with a line number if there is an error message.
As, at the moment It's not clear if it's all from one function/class or separate places.
Hastebin is a free web-based pastebin service for storing and sharing text and code snippets with anyone. Get started now.
I would like to preface this is my first big unity project, ive only ever done small games and almost always 2d, so I have no idea if Im following best practice but I am really trying too
I am also open to just changing the implementation if I've done it poorly, just after a bunch of research this is the best I could do...
That's a lot of calculations to figure out what's wrong just from looking at the code. I suggest debug logging all the intermediate values and/or do some visual debugging with debug rays to see that the calculations produce the values that you expect.
That way you'll be able to narrow the issue down to a certain line of code(or several) that are actually the cause.
Also, the value of step debugging can't be overstated
have you confirmed with either a log or a breakpoint whether OnCollisionEnter is actually being called or not?
okay but have you confirmed with either a log or a breakpoint whether OnCollisionEnter is actually being called or not?
nooo, i have never used those before let me read it agian
Debug.Log should have been like the first line of code you wrote in unity
im self taught
well you're clearly not learning the fundamentals. you should consider going through some basic courses to learn what you are actually doing
u suck
well i'm certainly not going to try helping you now
oh my bad, i'm guessing what you really wanted was for me to write the code for you so that you didn't have to do any work at all to figure out what the issue was. i'll come over and write Debug.Log("the code works"); for you so that you can see whether the method is actually being called
you should not try and help people if you are not skilled at doing so
its art
i have put a lot of hours into learning this
and the last thing someone wants to hear is that they are not validated
when they are trying to learn
stop making excuses about why you don't understand the bare minimum you need for unity and start putting effort into solving your issue
You might've got a different response in #💻┃code-beginner , but in the general channel we expect you to be able to do some debugging on your own. When you say that you've never used any of the debugging features, we know that you haven't done proper learning yet.
In which case the best advice we can give you is to direct you towards learning the basics.
Yes, this is true, but please, just move them to #💻┃code-beginner and the tutorials there instead of the hostile approach. Even if they're responding valuelessly, they are also right that this approach only harms
I'm pretty sure that there is a feature to make some serialized variables show up for example when another serialized bool variable is set to true, but I am unable to find it
that is not a feature by default. you can use something like NaughtyAttributes or Odin Inspector which have attributes for that. or you can write some editor code yourself for it
Oh, I thought I had seen some stuff like that, but perhaps I was mistaken, thanks!
You could technically do it yourself with an editor script
NaughtyAttributes is really good. strongly recommended
it just has a bunch of basic attributes to do things that Unity couldn’t be bothered to implement
@steady moat We don't allow discussions on decompiling here, including sharing tools on how to do so.
I'm having trouble with my code, and I'm wondering:
If i have multiple scripts that add an onClick listener onto a button, will all the Listeners be triggered when I press this button, or only 1 of them?
everything subscribed to the button's onClick event will be invoked when the method is invoked
okay that would explain my bugs. is there a way to avoid this? like instead of adding an onClick listener, replacing it?
im working with multiplayer, and the script is added to the playerpreffab. But since there are multiple players, the script is also called multiple times
subscribe at runtime via code. then you can choose whether you should or should not subscribe based on whether the object is the local client or whatever your criteria is
well i managed to get it working by removing all the listeners on it first, and then adding 1. this way only the last player that connects will not get it removed. I know this is bad practise, but I have little time left to finish it for school. I will however change it later and only make it run once
Thanks for the help though!
public async Task WaitAndDoSomethingAsync()
{
await Task.Delay(TimeSpan.FromSeconds(0.1)); // Wait for 0.1 seconds
// Code to execute after waiting
Console.WriteLine("Waited for 0.1 seconds, now doing something.");
}
public void DoSomething()
{
// Start waiting and doing something asynchronously
WaitAndDoSomethingAsync().Wait();
}
is doing something like this bad? atm the class isn't a monobehavior
Bad how? Isn't this a pretty standard case for delaying things?
If you went with a timer based solution you'd need another layer coordinating multiple calls to the function over time
E.g. a MB with Update to coordinate it
it uses
threading.tasks
which for some reason thought was bad to do inside of unity
It's fine to do, but you need to understand the nuances of when your code is running on the main thread vs background thread.
In this case Unity will run it on the main thread
If you use Task.Run you'll get a background thread
Background threads are also fine as long as you understand the limitations like not touching Unity objects
gotcha...I think
Im wanting to delay creating bullets so its in like a tiny "wave" instead of all at once
void CreateBulletSetStats(Vector3 position, Quaternion quaternion, float speed)
{
Bullet fireball;
fireball = BulletPooling.instance.bulletPools[bullet].Get();
fireball.transform.SetPositionAndRotation(position, quaternion);
fireball.SetSpeed(speed);
fireball.Fire(fighter.stats.attackDmg, fighter.tag, bulletType, fighter.enemyTarget);
}
You'll want to also look into Unity's Awaitable (2023+) which gives much better async support than using System.Threading stuff
it would call this function inside the task
Also if you want a consistent pattern you might need finer grained control over the timing which means something like waiting for FixedUpdate and maintaining your own timers
WaitForSeconds kind of stuff will "leak" milliseconds and make things look uneven.
If you end up wanting to use async and you’re using a pre-2023 version there’s the popular UniTask package on GitHub too
I'll check that out thanks
I dont plan to use async hardly ever so hopefully it just works as I have rn
welp, something went horribly wrong
{.....
WaitAndShoot(wait100ms).Wait();
WaitAndShoot(wait200ms).Wait();
}
TimeSpan wait100ms = TimeSpan.FromSeconds(0.1);
TimeSpan wait200ms = TimeSpan.FromSeconds(0.2);
public async Task WaitAndShoot(TimeSpan waitTime)
{
await Task.Delay(waitTime); // Wait for 0.1 seconds
Quaternion rotation;
int randomNumber;
for (int i = 0; i < 3; i++)
{
randomNumber = UnityEngine.Random.Range(-10, 10);
rotation = Quaternion.Euler(0, 0, randomNumber);
CreateBulletSetStats(fighter.firePoint.position, fighter.firePoint.rotation * rotation, projSpeed);
}
}```
this shouldn't be running in the background right? not sure why it crashes unity
Here is the main code it runs once the task "executes"
void CreateBulletSetStats(Vector3 position, Quaternion quaternion, float speed)
{
Bullet fireball;
fireball = BulletPooling.instance.bulletPools[bullet].Get();
fireball.transform.SetPositionAndRotation(position, quaternion);
fireball.SetSpeed(speed);
fireball.Fire(fighter.stats.attackDmg, fighter.tag, bulletType, fighter.enemyTarget);
}
I would recommend against using the Task api without a Unity integration like the 2023 awaitables or UniTask. You’re asking for trouble unless you know what you’re doing. For instance, Task.Delay does not respect Unity timing or time scale
gotcha, attempting to figure out just doing a coroutine with the UniTask right now
but they wrote a 20 page paper on using it 😭
UniTask exists so you don’t have to use coroutines
Coroutines are a byproduct of Unity not supporting modern c# features like async for a long time.
Now that they do, there are fewer scenarios where coroutines are optimal/necessary
You can wrap coroutines in a UniTask for compatibility/legacy purposes, but if you are the one writing asynchronous code it is not necessary to use coroutines at all cuz async supercedes their functionality and performance
It’s almost a mirror of the Task api, the class is just called UniTask instead and there’s a couple edge case differences like how you should return async UniTaskVoid instead of async void for exceptions to be captured correctly
thanks, found a random youtube video which hopefully got me there
WaitAndShoot(wait100ms);
WaitAndShoot(wait200ms);
break;
}
}
TimeSpan wait100ms = TimeSpan.FromSeconds(0.1);
TimeSpan wait200ms = TimeSpan.FromSeconds(0.2);
public async void WaitAndShoot(TimeSpan waitTime)
{
await UniTask.Delay(waitTime);
Quaternion rotation;
int randomNumber;
for (int i = 0; i < 3; i++)
{
randomNumber = UnityEngine.Random.Range(-10, 10);
rotation = Quaternion.Euler(0, 0, randomNumber);
CreateBulletSetStats(fighter.firePoint.position, fighter.firePoint.rotation * rotation, projSpeed);
}
}
will see if it works lol
and it doesn't crash now!
thanks @autumn field never would have found that github by myself 🙂
last time I ran into this issue I had to redo like 3 classes to make them all monobehaviors lol
No problem. If you have the patience I do recommend you read the docs since there’s still many ways to shoot yourself in the foot. But definitely less ways to mess up than using the standard Task api haha
Hey, I have problem with my collision
public void OnTriggerStay2D(Collider2D collision)
{
Debug.Log("collision");
if(collision.gameObject.CompareTag("Player"))
{
Debug.Log("2");
_currentTime += Time.deltaTime;
if(_stage == 0)
{
ChangeState();
}
if(_currentTime > TimeBetweenStages )
{
_currentTime = 0;
ChangeState();
}
}
}
(i tried bout OnTrigger and OnCollision)
i tried with and without trigger collider
and thats the player
it doesnt even log "collision"
I think the tile might need a static/kinematic rigid body
when i added one my game starts to lag
for some reason
and i have like 50 tiles on the map
so having 50 rbs wont work here
Did you set the rigid body to be static?
yep
Hmm maybe there’s another configuration that will work
The bottom of this page on the docs shows the requirements for trigger/collision events between two bodies
Looks like the tile doesn’t need a rigid body to receive trigger events if it’s static
Tho this is potentially just for 3D physics.
I don’t see another interaction matrix for 2d physics tho
ah thats so stupid
i guess i'll have to use something like OverlapBox or smth
but for some reason
on a different scene
i have this
private void OnTriggerStay2D(Collider2D other)
{
if (!colliders.Contains(other.gameObject) && other.transform.CompareTag("Player"))
{
MainMenuManager.Instance.PlayersInsideStartingArea++;
colliders.Add(other.gameObject);
}
}
and it works just fine
with player only having rb
You might be able to get better performance by using OnTriggerEnter/Exit2D instead of Stay and incrementing a timer yourself until exit is called
Just a hunch
but i can have multiple players
standing on the platform
and i need to increment the timer when atleast one player stands on it
also, why it works in this case then
it doesnt make any sense
You can still handle that
OnTriggerEnter2D:
if (other is player)
player count++
OnTriggerEnter2D:
if (other is player)
player count—
// somewhere else, like Update or a coroutine
if player count > 1
timer += timeStep
are the components different on the tile than the player? does the collider have a different setting?
nope and nope
Just checking, cuz in the first screenshot, the tile does not have Is Trigger set to true like the Start Game Area
yeah, i was testing smth
I’m also assuming the player is configured the same when touching the start area vs a tile.
yup
The only other thing I can think would be if the game objects are on a certain layer that doesn’t interact with one another. But if they’re colliding I don’t think that’s it
Might be worth asking again in #⚛️┃physics
Im on my phone so I can’t test anything and I’m probably just forgetting something obvious.
Continuation of a conversation from the talk channel about my code behaving differently when game is started from different scenes @heady iris
This is my dialog manager: https://gdl.space/hahimufapo.cs
And this is how im calling it in my NPC Controller script: https://gdl.space/axuyigajix.cs
I don't know if its notable or not but if I update my code the new behaviours apply to both versions so its essentially always broke in one scene or another.
looks like you subscribe to an event but never unsubscribe from it.
If you load another scene the event will still try to call the event on the script in the old scene which has been destroyed then
I recommend subscribing/unsubscribing in OnDisable()/OnEnable()
Interesting are you talking about my OnChoiceSelected event?
ye
Interesting theory and forgive me if im wrong but I dont think thats the problem, that event is only called when I have dialog choices but the issues im encountering are not related to choices and just testing quickly by never subscribing to the event doesnt solve the issue
hello guys I am loading 2 scenes together one for managers and the other one is the main scene so my manager scene override my main scene lighting how to solve this problem if anyone have any idea
any reason why the managers need to exist in a different scene?
Yes the manager scene need to persist in the duration of the game
can't you just make em DDOL?
yes I thougt of it and it works for me but I want to know why this is happening and how can I prevent it in other cases
why is my joystick not working? I am trying to make a joystick to move my charater around in a mobile game here is my code: https://hatebin.com/equgnftulk
Do you ever call OnDrag() and OnPointerUp()?
inpector on the handle bar
yes here in the event
set the inspector to Debug mode and check if isDragging is actually set to true
dragging is false
Hey guys I’m trying to make a script where when someone presses a button an animation on plays then at the end if they press the button again it resets and plays again
I know this is quite simple or should be
It’s screaming a coroutine
But how would I approach this
?
{
while(!_playableDirector.time.Equals(_playableDirector.duration))
{
yield return null;
}
isEnd = true;
}
Ive tried this to wait until the end then set a flag and make an if in update that can use the flag
my full code is this
{
while(!_playableDirector.time.Equals(_playableDirector.duration))
{
yield return null;
}
isEnd = true;
}
void Update()
{
if (toggle.isOn)
{
_playableDirector.Play();
}
else if (isEnd && !toggle.isOn)
{
_playableDirector.Pause();
}
else
{
_playableDirector.time = 0;
_playableDirector.Evaluate();
_playableDirector.Play();
}```
If you're using Timeline, why not sending a signal?
I mean I could
ik for sure it enters the condition though
like that works
it's just the functionality isn't workign
😵💫
Where does the default dialog data live?
I've updated it to this
{
if (toggle.isOn)
_playableDirector.Play();
while (!_playableDirector.time.Equals(_playableDirector.duration))
{
while(!toggle.isOn)
yield return null; // wait for it
if (toggle.isOn)
{
_playableDirector.time = 0;
_playableDirector.Evaluate();
_playableDirector.Play();
}
yield return null; // wait every frame on the outer loop;
}
}```
but doesnt seem to work still
but it only plays when the toggle is released
I am using this package for REST API requests: https://assetstore.unity.com/packages/tools/network/rest-client-for-unity-102501
RestClient.Post<type>(url, data).Then(response =>
{
// ...
}).Catch(Proyecto26.RequestException error =>
{
// ...
});
Why doesn't this code work?
I get: Syntax error, ',' expected and 'RequestException' is a type, which is not valid in the given context
What do you mean by default dialog data?
RestClient.Post<>(url, data) - you need a type between the angled brackets <>
yeah I have that
but I left that out here
Post the whole code unedited, so I don't false trigger on errors that are not there
The errors are all on the line }).Catch(Proyecto26.RequestException error =>
Well the line on which the error is, is unedited. The rest does't matter, it's just for context. If I remove Proyecto26.RequestException the errors are gone
But where should I add the type?
Nowhere
I am getting the wrong kind of error type
It's inferred from the context
so I can't read data of it
I want to read error.Response but it's the wrong Type:
'Exception' does not contain a definition for 'Response' and no accessible extension method 'Response' accepting a first argument of type 'Exception' could be found (are you missing a using directive or an assembly reference?)
but Proyecto26.RequestException has a field called Response
Seems like .Catch accepts a delegate that takes in an Exception only
If you are 150% sure the exception will be a Proyecto26.RequestException at runtime, then you can cast it in the lambda expression
error => ((Proyecto26.RequestException)error).Response
could also type check it to be sure using the is operator
But the cast will fail if the exception is not of that type
If you're referring to the actual dialog itself that started as a list of strings which is a serialized field in my NPC Controller, then I wanted to implement dialog options so I started using ink and added a serialized field TextAsset also in the NPC controller for the JSON
well a runtime fail is better than a compile time fail😂
No, not really
It says it when looking at the object in debug mode
Maybe Post<>() has a generic overload that takes both the response type and the exception type?
But there should be a better way to do this right?
With a normal catch, you can do
try{}
catch (Proyecto26.RequestException error) {}
catch {}
So you seperate the different types of errors
Of course I can't know for certain that 100% of the errors are gonna be Proyecto26.RequestException, but they are far more common
I don't think so, there is Post<>() and Post(), nothing else
Seeing the docs Post<T> it takes in a Action<RequestException, ResponseHelper, T> delegate type, investigating further
They're all void though, so I might be looking at the wrong thing since you couldn't possibly be using .Then on void
yeah it isn't a void
You should be able to navigate to definition to see the exact declaration
public static IPromise<T> Post<T>(string url, string bodyString)
{
return Post<T>(new RequestHelper { Uri = url, BodyString = bodyString });
}
public static IPromise<T> Post<T>(RequestHelper options)
{
var promise = new Promise<T>();
Post<T>(options, promise.Promisify);
return promise;
}
public static void Post<T>(RequestHelper options, Action<RequestException, ResponseHelper, T> callback)
{
options.Method = UnityWebRequest.kHttpVerbPOST;
Request(options, callback);
}
Okay now to look at what IPromise<T>'s Catch method looks like
hmhm where should I look?
/// <summary>
/// Handle errors for the promise.
/// </summary>
IPromise Catch(Action<Exception> onRejected);
/// <summary>
/// Handle errors for the promise.
/// </summary>
IPromise<PromisedT> Catch(Func<Exception, PromisedT> onRejected);
there is this
Okay so Exception it passes, cast at your own risk
So what happens if I cast and it fails?
hmmh I have an idea:
Can I just do something like:
RestClient.Post<type>(url, data).Then(response =>
{
// ...
}).Catch(error =>
{
try
{
RequestException ex = (RequestException)error;
handleError(ex.Response);
}
catch
{
handleError(error.Message);
}
});
I strongly believe the exact opposite. A compile time error is always preferable to a runtime error
Runtime errors affect the user, compile affects the developer. There is no context where a runtime error is better. Unless it is a runtime resolvable runtime error I guess
well yeah out of context it's not really true haha, I realise that
Well in this context: The code didn't work 100% of the time because of an compile error, while with casting it it would work 90% of the time, and the other 10% I could just catch the runtime error
The GitHub repo of the project is also incomplete, didn't find any IPromise<T> interface nor the Post<T>() methods returning an implementation of it.
Most classes are partial though, so it may be exluded deliberately, although I don't see a reason for anyone to do that
Still would take the compile error lol. I would rather it never run than fail 10% of the time randomly haha.
But no worries. I'll drop it
Maybe not 10% but 0.000001%
Is there a way to have a 2D joint with constant pulling force and affected by gravity ?
I tried with the Spring Joint 2D but the force is proportional to the distance of the 2 Rigid Bodies and not constant.
I also tried with a Distance Joint 2D but I cannot control the pulling force and it seems to change the gravity a bit because the object I've attached the joint to is slowed down although it's going into the same direction as the pulling force of it.
It's hard to explain it aha
Maybe I should apply a force to the direction instead of using a joint ?
If you want a constant force instead of a complex spring, yes just apply a constant force in the direction of your hinge
What is the easiest way to handle JSON data like this:
{
"error": {
"code": 400,
"message": "EMAIL_EXISTS",
"errors": [
{
"message": "EMAIL_EXISTS",
"domain": "global",
"reason": "invalid"
}
]
}
}
I did it like this:
[Serializable]
public class ErrorResponse2
{
public List<ErrorResponse3> errors;
public int code;
public string message;
}
[Serializable]
public class ErrorResponse3
{
public string domain;
public string reason;
public string message;
}
[Serializable]
public class ErrorResponse1
{
public ErrorResponse2 error;
}
And then I used Newtonsoft JSON since the JsonUtility didn't work to deserialize it...
But that's a lot of work. Is there a better way?
Oh it seems there is the keyword dynamic for this?
And it seems you need to change the Api Compatibility Level to . NET 4.x and Scripting Backend IL2CPP for that
But is that possible with WebGL in Unity 2021 LTS? The option is grayed out...
I think I solved it by changing it to .NET Framework
JsonUtility didn't work to deserialize it
this is surprising. also you do not need to use .net 4.x for newtonsoft json to work. also, you cannot use the dynamic keyword for il2cpp targets
you made some other error. your modeling of the classes is fine, it will decode with JSONUtility correctly. you can test this easily by copying and pasting your string, and trying to deserialize it in a Start
do you have a screenshot of your webgl game?
audio must start from a trusted user interaction like a click in web browsers. do you have a screenshot of your game?
what is the URL you are trying to access? what is your application? the request in the browser has the browser's user agent, and the API you are trying to access is reading the user agent and changing its response. also, the browser uses CORS, so the API might not be accessible, and you are receiving some other response instead of a proper CORS rejection
Anyone know how to yield the result of a Coroutine? The documentation says it can be done, but doesn't give an example.
well it isn't that surprising tbh, I've had that many times. You can try it for yourself with the info in this message: #archived-code-general message
{"error":{"code":400,"message":"EMAIL_EXISTS","errors":[{"message":"EMAIL_EXISTS","domain":"global","reason":"invalid"}]}}```
The issue is that putting yield return StartCoroutine(CoroutineB()) inside CoroutineA() doesn't actually wait for the started coroutine to finish. It just waits until there is a yield return somewhere inside CoroutineB(). So even if there's more code after yield return in CoroutineB(), CoroutineA() will already keep going.
I was able to use dynamic by using Mono (I was unable to change to il2cpp for some reason) and .NET Framework
.net 4.x was no option
Well no, it won't serialise it, it just gives null when using JsonUtility. Luckily Newtonsoft json does do it
.net framework is .net 4.x
and yeah, cannot use dynamic on IL2CPP
https://docs.unity3d.com/Manual/ScriptingRestrictions.html
I just remembered that that would not work since it's for a grappling hook which can move movable objects. Let's say the player hooks another object with the same mass, they would end up in the middle of where they were. The joints made this easy...
Apply the same force on the grappled object in the direction of the player
Would be my first guess, actual math behind that might be a bit more complicated if you want it realistic
Hm yeah but if you grab a wall, you will not get the same velocity because it does not move
Then apply half to each if you grapple a movable object, full on the player if its static
The joints were perfect for this physics but I can't make one just pull at the same force everytime
yielding a StartCoroutine call absolutely does wait for the coroutine to finish before proceeding.
void Start()
{
StartCoroutine(ACoroutine());
}
public IEnumerator ACoroutine()
{
Debug.Log("Started Coroutine A");
yield return StartCoroutine(BCoroutine());
Debug.Log("Coroutine B should be done by now");
}
public IEnumerator BCoroutine()
{
Debug.Log("Started Coroutine B");
yield return new WaitForSeconds(1.5f);
Debug.Log("Coroutine B halfway done!");
yield return new WaitForSeconds(1.5f);
}
Yeah but I may have an object at some point that is like 1.3 times the mass of the player for example I can't do it case by case
No. I can say for a fact it does not, because I'm having this problem. Even the documentation says that it doesn't. Straight from the documentation : The StartCoroutine method returns upon the first yield return, however you can yield the result, which waits until the coroutine has finished execution. There is no guarantee coroutines end in the same order they started, even if they finish in the same frame.
So the first time you call yield return in your called Coroutine, the first Coroutine will stop yielding.
i literally just showed you that it works
using System;
using System.Collections.Generic;
using UnityEngine;
namespace DefaultNamespace
{
public class Test
{
[Serializable]
public class ErrorResponse2
{
public List<ErrorResponse3> errors;
public int code;
public string message;
}
[Serializable]
public class ErrorResponse3
{
public string domain;
public string reason;
public string message;
}
[Serializable]
public class ErrorResponse1
{
public ErrorResponse2 error;
}
[RuntimeInitializeOnLoadMethod]
public static void RunJson()
{
var str =
"{\"error\":{\"code\":400,\"message\":\"EMAIL_EXISTS\",\"errors\":[{\"message\":\"EMAIL_EXISTS\",\"domain\":\"global\",\"reason\":\"invalid\"}]}}";
Debug.Log(JsonUtility.ToJson(JsonUtility.FromJson<ErrorResponse1>(str), true));
}
}
}
this works correctly
you can see for yourself in the debug.log
so i think you have made a few mistakes along the way on this journey
however you can yield the result, which waits until the coroutine has finished execution
straight from what you just copied.
if you actually yield the StartCoroutine call then it will wait for execution of that coroutine to complete before continuing the outer coroutine
and in case the previous code was not obvious enough for you:
https://paste.mod.gg/pytimzbodvqa/0
Coroutine A would have finished in under 1 second if it returned to execution after Coroutine B reached its first yield. but you can clearly see it took all 20 seconds for it to finish because that is how long Coroutine B took
compare masses of player and object, apply forces based on that
1u mass on player, 2u on object = 1/3 force on player, 2/3 on object
Wouldn't it be simpler with joints ? lol
Like Distance joint and Spring joint are almost what I want.
Problem with Distance joint is the pulling force not adjustable and the gravity weirdly applied,
and the problem with Spring joint is just that it's force is relative to the distance. Maybe there is math to make the SpringJoint frequency equal to pulling with the same force at any time ?
what effect are you trying to give? if you want a constant force from A to B, that's super easy without joints.
Spring joint also allows you to change the damping ratio and frequency at runtime
I want to do a grappling hook that when attached to a wall will pull the user with the same force at any time. So a constant force.
If an opposite force is being applied on the player that is stronger than the grappling hook then the grappling hook will extend.
Its starting sound on web page but user must be click on screen. I want to make it start byself.
if its the same force everytime, in the direction from player to connection point, then add force sounds way easier. Otherwise you'll be fine tuning some joints and trying to adjust the damping/frequency based on some equation if one exists.
The grappling hook extending doesnt exactly matter since you'd be using the players current location and not the location of when they started hooking. The hook itself is just visual so that'll be like from your line renderer or however you choose to represent the hook rope
it's a restriction by browser vendors, sorry
do you understand what i mean?
anyway, you probably want to remove newtonsoft json, go back to il2cpp (that's the only thing that's supported by webgl anyway), go back to net standard 2.1, etc. etc.
But as I said earlier it's getting complicated to replicate real physics with this since the player will not only hook static objects but movable objects with different mass too. The joints handled that very well and simply
do you really need the spring joint to give a constant force the entire time? This already would be quite an unrealistic effect for physics
you could try to adjust the frequency based on distance to the object
This is my attempt with the Distance Joint. But something feels weird. It's pulling with the same force but the grappling hook cannot get longer it seems. And sometimes I slow down while going into the direction of the pulling force.
what do you mean the grappling hook cant get longer? a distance joint is also basically just a spring joint
https://docs.unity3d.com/Manual/class-DistanceJoint2D.html
It does apply a linear force to both connected items, using a very stiff simulated ‘spring’ to maintain the distance. You cannot configure the properties of this ‘spring’.
the grappling hook is just a visual, the objects connected to the joint would move further away if you were applying enough force to counteract it
This is with the spring joint.
It feels way more smooth and natural. For example you can see me doing circles around a block and I cannot do that with the Distance Joint because it does not "stretch". And the Spring joint can
But yeah the only thing is that the further I am the more force is applied.
The Distant Joint will always take the same time to travel to point A to B no matter the force applied in the opposite direction
With tests, a spring joint with 0 frequency makes it the stiffest possible and it makes the exact same result as the distance joint
So yeah the only thing I'm thinking is trying to change the frequency based on the distance so that it "cancels" the spring force
{
float elapsedTime = 0f;
while(elapsedTime < duration)
{
float t = elapsedTime/duration;
t = animationCurve.Evaluate(t);
flipModel.transform.position = Vector3.Lerp(flipModel.transform.position, flipModel.transform.position + new Vector3(0, offset, 0), t);
foldModel.transform.position = Vector3.Lerp(foldModel.transform.position, foldModel.transform.position + new Vector3(0, offset,0), t);
elapsedTime += Time.deltaTime;
yield return null;
}
}
```
Anyone know why Unity 2023.3.4 doesn't do reproducible builds when set to build the same way each time? GlobalGameManager is the file that changes
hey guys I wrote this script to make a simple translation animtion
do you know how I could create a bounce effect
and ease the animation
Use an animation curve 🙂
I have :(((
it doesnt create the same bouncing effect I want
where it bobbles
I was looking and maybe Mathf.PingPong idk tho
then change the curve
you can also use a tween library
what happened to the code we had yesterday?>
you changed it
the Lerp is now incorrect
you need to save the start and end positions and use those in the lerp
not the current positions
that's why it's not working
yes this one is slightly different though im no longer trying to swap but rather just move two things up
it doesn't matter - you still need to save the start/end positions at the beginning and use those throughout the lerp
otherwise you will not get what you want
ok im probably being dumb here but my start was supposed to be foldModel.transform.position, foldModel.transform.position and then its ending position will be shifted by an ofset so the same thing + new Vector3(0, offset,0)
ok great so save all those positions in variables
so they don't change during the animation
ok ok I see yeah im being dumb makes sense
ok it works now nicely
can you briefly explain why though its necessary
I mean it's as simple as the fact that Lerp takes in (startingPosition, endingPosition, t) as parameters
since you were putting in something OTHER than those expected parameters, you can only expect garbage to come out of the function
ok lol I was really having a brain fart thanks again @leaden ice
Hey, my Dash is being executed even though not all conditions are met. What am I missing?
https://hatebin.com/jqbeqgllnu
Did you log all conditions before the function
Either you are calling the function elsewhere or all the conditions are met. There's no other option
no, I'll check
but will it say something other than the debug inspector?
nothing in your screenshots corresponds to any of the variables in that line of code. Except _hasCooledDown which is FALSE in your screenshot which will already make it not run
You have 4 bools, so verify that they are correctly flagged to the required conditionn
yes, but it does run. _isDashing is only set to true at one place. inside the private Dash() function. see line 7. https://hatebin.com/iaheabdrgp
isDashing isn't relevant
since it's not in the if statement
just print the values out
anything else right now is a waste of time
the screenshot shows the debug inspector is dashing is true and is cooling down is true.
is dashing is initialized at false and set to true only when Dash() is called, which should only be called when hasCooledDown is true, but it is not.
the debug inspector isn't relevant because you can't possibly read it fast enough to matter
yes, i'll do gimme a sec
all that matters is the state of the variables right at the moment before the if statement runs
you get that through Debug.Log or with the debugger
ah forgot isdashing dammit
so it is false. and it is also marked as "true" in the debug inspector. why does the debug inspector lag?
but my player is still dashing.
Not sure how frequently the inspector updates. It's at most once per frame, and variables can change value during the course of a single frame between when it might be rendered
show the code for this
also make sure Collapse is not turned on in the console window
so this is the dashing stuff:
https://hatebin.com/qqanqhmwrd
this is my update: (printing begins at line 87)
if (_dashButton.WasPressed && CanDash && _hasCooledDown && !_isLocked)``` doesn't care one way about `_isDashing`
all of the other conditions are satisfied as per your screenshot above
Again: isDashing is set to true in the Dash() function. I'm dashing but it is set to false
the isDashing stuff is at line 21
what does that have to do with this code though
in the update
if _isDashing is becoming false it's because StopDash(); is running
unless it's happening elsewhere in the script (not shared)
so for the background: dashing generally works in my game. however, when spamming the button and dashing against walls it can lead to a game-breaking bug, where the player is stuck in the wall and these are the relevant properties. so i see that i'm dashing because i'm stuck in the wall with my dashing animation, but isDashing is set to false. i'm not sure how this is possible
Well clearly there's some bug with the code that's calculating the dashing positions and distances etc
so you should be debugging that code
_initialXPosition = CenterOnTile(transform.position.x);
float dashDirection = transform.localScale.x;
float targetXPosition = _initialXPosition + dashDirection * _dashDistance;
if (dashDirection * transform.position.x >= dashDirection * targetXPosition)```
all this stuff
also you're not checking if you are already dashing before allowing another dash to happen
that is a good idea. wait a sec please
I feel like you have a bit too many variables that mean the same thing too which is leading to confusion. what's the difference between _isCoolingDown and _hasCoo0ledDOwn other than being opposites?
I also don't see _isCoolingDown = true; anywhere so I don't think the cooldown is being processed at all
oh I see, it's in StopDash()
so really don't you need to just add !_isDashing to the if statement about whether you can dash to prevent spamming?
which is kinda what I was saying here
tried that just now. still managed to get stuck to the wall :/
is cooling down is just starting the timer (line 98)
hasCooledDown is what enables the dash
are you happening to turn aroiund when you get stuck in the wall?
my guess is you're inverting the x scale which is going to bypass physics and invert your collider, putting it inside the wall, hence you get stuck.
ah maybe. im pressing left and right like crazy. the debug inspector said is facing right was false while indeed i was stuck looking to the left, but since it might lag i will log that now
i still have the frame stopped now. the colliders look fine
it is also symmetrical
Wait you're also doing this:
transform.position = terminalPosition;
Try commenting that line out
that could be teleporting you into the wall
you generally never want to set the Transform position directly when using physics
just tried that. still managed to get stuck. the reason i do that even though it seems kind of redundant is to make sure my player really ends up exactly at the center of a tile
also what i mean by being stuck to the wall is that i simply dont stop dashing.
i tried dashing with a timer first and then doing something like speed = distance/time, but it was imprecise
i simply dont stop dashing.
Well yeah your code requires you to travel some exact distance before it stops. It's also using some sketchy math to get there
if you hit a wall first you won';t ever travel the required distance
thats why i have this here: https://hatebin.com/baqqohjjho
I don't really understand how that's supposed to work
but this seems very complex/convoluted
it's not surprising something is slipping through the cracks
why not do a boxcast or something before dashing to determine how far you can dash
yes, unfortunately it is, but i couldnt find another way to get my player precisely into the middle of the tile
I'm not sure I understand what you mean by that or why it's desirable to be in the center of a tile
Is this a grid based game?
its a pixel art game with a tile grid, its basically a metroidvania, but i like the snappiness of reaching the middle of a tile and i use that a lot for parcours
basically everything that could hinder me from dashing further will stop the dash
so if its a trigger i'll just dash past it, if it is solid StopDash() will be called
I would just calculate where the target tile center is and figure out how many physics frames it will take to get me there at the game's dashing velocity. Then just set the velocity and wait that many physics frames (with a coroutine)
why is the font so nice
you may need to adjust the velocity down or use MovePosition on the final physics frame to reach the exact point
unless you're willing to have different overall dash velocities to satisfy that snappiness
console -> three dots menu -> monospace font
oh shit thanks bro :)
no i only have a single one. that sounds like a good idea, but why would it stop my dash other than what I am doing now?
you wouldn't have to rely on hackiness like OnTriggerEnter
i would stil crash into a wall, the target tile will not be reached and the wall collider will be checked as !isTrigger and StopDash will be called just like it is now
the dash would always last a certain number of physics frames no matter what
aah i see
so i need a combination of your idea and a boxcast to determine if something is between my player and the target tile?
or do you mean i would simply stop getting stuck after the dashtime?
i mean its about 0.16 seconds so i could live with tht
*that
I would combine it with boxcast
come up with a shorter duration based on the distance the boxcast travelled before hitting something if it hits something
sorry i dont understand that sentence
Do a box cast. If it hits something, get the distance and adjust the dash time accordingly
basically:
- boxcast to get the distance you will go unimpeded
- take the next closest "center of tile position" closer to the player from that position
- calculate the time it will take to go there
- divide that time by Time.fixedDeltaTime and FloorToInt to get an int. Call this N
- start dashing.
- wait N physics frames
- stop dashing
why do you do a stop dash, why don't you just calculate the distance before dashing
assuming it's like some type of teleport
Thanks! Will try that 🙂
hm. i remember vaguely having tried that and there was a reason
ah yes because i feared i would go into walls, so yeah with a boxcast it should be fixed
theres more than only walls which i can bump into like bouncers and doors, so i thought !isTrigger was the best option
{
// right-click
if (Input.GetMouseButtonDown(1))
{
Debug.Log("Hotbar button right-clicked!");
clickedButton = buttonClicked;
ShowAbilityDropdown(clickedButton);
}
// left-click
else if (Input.GetMouseButtonDown(0))
{
Debug.Log("Hotbar button left-clicked!");
GameAction action = GetActionFromButton(buttonClicked);
if (action != null)
{
if (action.isOnCooldown)
{
// If the action is on cooldown
// set the button's text to show remaining cooldown time.
float remainingCooldown = action.GetRemainingCooldownTime();
buttonClicked.GetComponentInChildren<TMP_Text>().text = remainingCooldown.ToString("0.0");
}
else
{
// If the cooldown is over
// execute the action and start the cooldown.
action.Execute();
action.StartCooldown();
buttonClicked.GetComponentInChildren<TMP_Text>().text = "";
UpdateCooldownText(buttonClicked, action);
}
}
}
}
// get the action associated with a button based on its sprite
private GameAction GetActionFromButton(Button button)
{
Image buttonImage = button.GetComponent<Image>();
if (buttonImage.sprite != defaultPlaceholderSprite)
{
foreach (var action in learnedActions)
{
if (action.LoadIcon() == buttonImage.sprite)
{
return action;
}
}
}
return null;
}
private IEnumerator UpdateCooldownText(Button button, GameAction action)
{
while (action.isOnCooldown)
{
float remainingCooldown = action.GetRemainingCooldownTime();
button.GetComponentInChildren<TMP_Text>().text = remainingCooldown.ToString("0.0");
yield return new WaitForSeconds(0.1f);
}
button.GetComponentInChildren<TMP_Text>().text = "";
}
public void StartCooldown()
{
lastExecutionTime = Time.time;
isOnCooldown = true;
}
I have a script that assigns the hotbar its sprite and on click executes the spell or abilty that is associated with that sprite. I wanted to add a visual countdown so there is a empty text on the sprite and I set up some code for it to work, however it only shows it after you click on the button after you initially called it and excuted. If I click the button any number of times during the cooldown timer it updates the text with that float value. What do I have wrong here?
It's unclear where the UpdateCooldownText coroutine is being started from
if it's being started at all
Oh yeah looks like you're not even starting the coroutine
you're just doing UpdateCooldownText(buttonClicked, action); which won't do anything
to start a coroutine you need to use StartCoroutine
e.g.
StartCoroutine(UpdateCooldownText(buttonClicked, action));
yep that was it, dammit ty. something so simple to.
im trying to build a game with a deferred camera but everything render black, if i switch urp setting to forward it work. What could be wrong?
in editor all work fine with both
I'm trying to get the current animation that is playing and get the length of the clip but for some reason it keeps getting the previous animation
ive used GetCurrentAnimatorStateInfo and GetCurrentAnimatorClipInfo
and both give the same result
why do you want the length of the clip
Is there a way to check by code if a material is read-only material (the one that is greyed out and can't be edited)?
I'm making a sword combo system so I want to set a time frame that the player can click to continue the combo
Use animation events
im messing around with events for the first time, but is there any reason to use c# events over unityevents?
good rule of thumb is this: If you need to mess with it in inspector, use UnityEvent. Otherwise, always go c# event.
I actually didn't use event much myself(I use Action)
okay, that seemed to be the only difference i could notice
how does Action work compared to Event?
IDK that deep but Action is just easier to use for me
an action is just a delegate
oh gotcha
an event is something else entirely, an event only exposes the add and remove to these delegates. An event can only be invoked from within the same class
So if you just use a delegate/action without the event, anything can invoke your code
ahh thats where i was getting caught up
i think ill have to use delegates then
im having enemies broadcast when they die so towers in my game can remove them from their targeting lists
Thats fine with events, the enemy itself should be the only one notifying that its died
i need the towers to be notified too, since each tower stores its own list of enemies within their range
just destroying the enemy leaves me with a null element
the tower would subscribe to the event
but didnt you say the event has to be called within the same class?
hm can you show part of this code? sounds like your tower is handling things that the enemy should be
Using this list to store all the enemies that are within tower range (current target is just the closest enemy in this list)
public List<GameObject> enemies = new List<GameObject>();
Using this trigger to see when the bullet hits and then damage the enemy via the takeDamage method
void OnTriggerEnter(Collider other)
{
Debug.Log("Bullet Reached Target");
if(other.gameObject.tag == "Enemy")
{
HitTarget();
}
}
void HitTarget()
{
EnemyScript e = target.gameObject.GetComponent<EnemyScript>();
e.takeDamage(damage, gameObject);
Destroy(gameObject);
}
public void takeDamage(float damage, GameObject damagerBullet)
{
currentHealth -= damage;
if(currentHealth <= 0)
{
TowerBehavior t = damagerBullet.transform.parent.gameObject.GetComponent<TowerBehavior>();
//t.enemies.Remove(gameObject);
Destroy(gameObject);
}
}
^ this last snippet was giving me errors
so i wanted to just use an event to tell all towers the enemy died, remove that enemy from their lists, and then destroy the enemy GameObject
yea I think that part is definitely questionable. your damage function can know what damaged it, but that'd be more for visuals, debugging, or a smart AI knowing who to go after.
You should just have the towers subscribe to the enemies death event when they're in range
And when they leave the range, unsubscribe
right. and with the way i have it right now, only the tower that hit it with the killing blow will know to remove it from its list
still having a bit of trouble understanding the different uses of event, delegate, and action though
the simplest way would be like
public event Action OnDeath;
public void TakeDamage(float damage)
{
// whatever damage calculation done here
if(currentHealth <= 0)
{
OnDeath?.Invoke(); // null check to see if anything subscribed before invoking
Destroy(gameObject);
}
}
And when your enemies come in range of the tower you do
enemy.OnDeath += //Some method that removes the enemy from the list
an action is a delegate.
namespace System
{
public delegate void Action();
}
its just one that doesnt return anything, but it can take up to 16 parameters.
A delegate is kinda like a function pointer if you know c++. In a sense its a way to reference a function.
An event just takes this delegate or action, doesnt let any other class invoke it, and lets implements custom add/remove code (to the delegate chain)
show the tower code that indicates an enemy is in range
OHHHHH
that little pointer bit made it make sense
so the delegate is just a placeholder for what is actually called when a listener hears the event
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Enemy")
enemies.Add(other.gameObject);
}
so i would just add the event subscription in there when the enemy is added to the list
and then have a separate method in the tower that the delegate invokes
the delegate is the methods that are called when the delegate is invoked. Listener is more of a term used to describe something that subscribes to the event
yea pretty much
Heyo guys! I'm currently extending the Image component and just tried to put a public variable in the script but it doesn't show up in the inspector. Any ideas as to why? Much appreciated!
that part is called delegate chaining. If 1 enemy is seen by 2 towers, both would have a method added to the delegate chain. Events make sure that you arent overwriting the other tower's subscription.
and one more thing, how would i pass a parameter through the event? I'd like to have the enemy pass its own GameObject so that the tower can just pull it from its list
or is there a way to just see which GameObject invoked the event
Ya got any errors showing? Make sure the editor is compiling, otherwise I've not tried extending from image before, so there could be some custom inspector stuff going on.
I've come to realize its because unity's components have their own editor script to hide and show relevant fields. extending from it means that editor script doesn't cater to my own fields
Class used on game object using UnityEngine; using System.Collections; using UnityEngine.UI; using System; [Serializable] public class UIButton : Button { public enum TestEnum {ON,OFF} public int testInt; public TestEnum testEnumVar; } Class used to override the inspectorGUI using UnityEngine; using System.Collections; usi...
just make another script and throw on:
https://docs.unity3d.com/ScriptReference/RequireComponent.html
You can try making a custom editor and calling base.OnInspectorGUI to draw the base inspector, and then draw your custom fields manually
(Though im not sure if inheriting from Image is valid)
yea you could just pass the enemy and do
public event Action<Enemy> OnDeath;
Then the method will use that as a parameter
im tired so im not sure if theres an alternative, you could use a lambda to not pass it in but then you cant remove the subscription. This might not actually be an issue for you but it could start to be one if an enemy keeps entering the trigger and keeps adding to the delegate chain
Yeah that might raise issues if there's a loop in the path and the enemy circles back to the tower
I think this will work, I just have to completely wrap my mind around it so it actually makes sense when I write it
yeah i realized that in doing so, all the normal image editor logic goes out the window and Im seeing variables i know damn well Im not supposed to be seeing all at once
Hey there, I have a randomly generated map with a dynamic size, and I'm unsure how to make the borders seem infinite... Right now they look like this:
What is wrong with that? Do you mean the little line across the purple thing on the left? What exactly are you trying to achieve?
I have a script with ExecuteInEditMode Attribute. Why does its OnValidate method execute in run mode?
I see, I used to call it from OnEnable
well, why is OnEnable called in play mode through..
why wouldn't it be?
ExecuteInEditMode means the script runs in Editor and Play. Not just Editor
what does [ExecuteAlways] mean then?
namespace UnityEngine
{
//
// Summary:
// Makes instances of a script always execute, both as part of Play Mode and when
// editing.
[UsedByNativeCode]
public sealed class ExecuteAlways : Attribute
{
}
}
That executes on Prefabs which ExecuteInEditMode does not
I see, then it makes sense.
anyone know how i can detect what material/colouir a object is and then change it in code
also i shoujld probably note, it is a prefeab and a 3d model (from blender)
Item newItemScript = newItem.GetComponent<Item>();```
Is there a difference between newItem and newItemScript here?
For example if I set the parent, can I use either one?
And if I pass the Item newItemScript to another function, can I use that to call functions on the GameObject?
I've noticed they are interchangable to some level, but would like to understand it better
Yes, because behaviours have a field for the gameobject they are attached to
Item knows about it's gameObject but newItem doesn't know about it's script without using GetComponent
so I guess newItemScript.gameObject just lets me access newItem?
you can also turn itemPrefab from a GameObject to a Item, then you can skip the GetComponent() call
btw SetParent is a method of Transform so it would be the same for both objects
yeah I think that's what confused me
Heh? The prefab has some more things in it I need
doesn't matter though
If you are cloning a Component the GameObject it is attached to is also cloned
https://docs.unity3d.com/ScriptReference/Object.Instantiate.html
ah yeah I know that, I just get the script cuz I need to do some things with it
ah you mean I can do Item newItem = Instantiate(itemPrefab); instead?
yes
Need to also change the prefab field type
and that will still get the complete prefab?
can't test it now cuz I have a lot more code to fix 😛
newItem.name = itemSO.name;```
This would set the gameObject name not?
Oh someone on the forum said it the other way around, that it was only available on IL2CPP
it requires JIT compilation in order to work which is obviously not possible with IL2CPP
What does [RuntimeInitializeOnLoadMethod] do?
well obviously...
I don't know what the difference is between Mono and IL2CPP so it wasn't obvious to me
I know IL2CPP stands for intermediary language to c++
and dynamic isn't a thing in c++
but that doesn't say everything
I want the border to continue as the background after the border ends
this was the forum post I was talking about btw
https://forum.unity.com/threads/missing-compiler-required-member-microsoft-csharp-runtimebinder-csharpargumentinfo-create.563839/
If by the border you mean the purple thing, then it looks completely fine to me. You are gonna have to be more specific and explain to me what exactly is wrong, tell me what to look for in the picture at least
And I don't see the border ending anywhere
So it is basically just a thing to execute the method when the scene loads?
literally the post right above that one contradicts it and actually provides the correct answer. il2cpp is AOT (or ahead of time) compiled, dynamic requires JIT (or just in time) compilation to work
i mean, not just when the scene loads. the documentation clearly states when the method would be invoked which is dependent on the enum you pass to the attribute
well I read that, but it doesn't say what I need to do to get it working...
I mean in this case
you need to not be using IL2CPP and you need to target .net framework
why do you even want to use dynamic anyway?
read my original post
link it because i'm not going spelunking to find it myself
Well i figured that out after some time, but I think you can understand why it is confusing for someone who doesn't know a lot about Mono/IL2CPP and .NET Framework / .Net Standard
ah you're using webgl which means you cannot use dynamic because it is IL2CPP
No?
at that point you may as well just deserialize into a Dictionary<string, object> if you must support deserializing into an unknown type. but it is certainly better to deserialize into a type you have created like you were trying to avoid
WebGL is only Mono I think
well I am using WebGL and also using dynamic
I haven't tested that, good point
exactly. WebGL is IL2CPP
https://docs.unity3d.com/Manual/ScriptingRestrictions.html
that literally supports what i just said
is there a more effecient way to do all of the rest ones like the one above ?
yeah, it would be to use collections instead of separately numbered variables. then you just use loops
define collections
array, list, other #💻┃code-beginner topics that are covered in the beginner courses pinned in that channel
what's the difference between ItemOne, ItemTwo, ItemThree?
aight ty
is different objects that i didnt really want to give them special names
hmhm interesting, but if you serialise into Dictionary<string, object>, can you also find nested data?
you should really just do it the hard, but correct, way instead of trying to avoid c#'s convenient type safety
there are even websites that will generate c# code based on json schemas you pass
OH SORRY I THOUGHT U WERE ASKING
yeah I used those
It looks to me like you have 3 different helmets and instead of swapping out the sprite of the display you have multiple displays and enable the one that got selected.
Okay then I have a question:
How would you name those classes it generates? And:
Where would you put the classes it generates
more like selecting one of the three
The thing is I don't want to make my code unreadable by putting those classes all over the place
you put them where it makes sense to put them. don't just drop them into random folders/files. it wouldn't have any effect on the readability of the rest of your code if you are organizing your code like a sane person
Well you just said how not to do it, I want to know how to do it.
you create the relevant types that you will need for deserializing the data. you put those types in namespaces/folders/assemblies where they are necessary. i don't know what else you are expecting me to say?
well so I asked about how to name them
So would you recommend to make a seperate file for the classes?
the same way you name any other object. give it a name that makes it clear what its purpose is
Well the thing is, I haven't made that json structure, so I don't really know what the purpose is
So the example I sent was a json response for if you make a sign up request and the email adress is already used. How would you name the 3 classes?
why are you consuming an API you do not know the purpose of?
of course I know the purpose of the whole json response, but not of the individual parts of it
as I said, how would you name the clases in my example?
just name them something that makes sense for you. i'm not going to do the thinking for you.
if their current terrible names are sufficient for you now, then just use those
you don't need to do all the thinking for me, only for this example, so I have an idea for how to do the rest
If you think the current names are "terrible", I would like you to give a better proposal...
it doesn't matter what I think. it's your code. use names that make sense to you. make your own decisions
and you're not going to bait me into making your decisions or doing the thinking for you so stop trying
okay if you don't want to do it it's fine lol
why wasn't it fine the first time i said i wasn't going to?
You said you weren't gonna do all the thinking for me, and with that wording I thought you thought I was asking you to give names for all the classes I was working with
Weird, this does work
I only changed
JsonUtility.FromJson<> to JsonConvert.DeserializeObject<> and I left the rest of my code the same
I can't reproduce the error so you're probably right
Debug.Log(equipment.transform.Find("LeftHand"));
Transform equipmentSlot = equipment.transform.Find(item.ItemSO.ItemType.ToString());```
what am I doing wrong?
What's on line 136?
the 3rd line Transform equipmentSlot = equipment.transform.Find(item.ItemSO.ItemType.ToString());
I can’t do nothing with the script, any help?
here's the fix
Are you sure? Double-check
Is there any way to use on pointer events on an object with a spriterenderer?
Ew: if (equipmentSlot.childCount != 0)
give it a collider, and give your camera the relevant Physics Raycaster component
oh and obviously you'll need an EventSystem in the scene
I see, thank you!
Ah nvm, I need to use the name of the itemType not try to conver the object to a string
{
try
{
await AuthenticationService.Instance.SignUpWithUsernamePasswordAsync(RegisterUsernameInput.text, RegisterPasswordInput.text);
}
catch (AuthenticationException ex)
{
// Compare error code to AuthenticationErrorCodes
// Notify the player with the proper error message
Debug.LogException(ex);
}
catch (RequestFailedException ex)
{
// Compare error code to CommonErrorCodes
// Notify the player with the proper error message
Debug.LogException(ex);
}
}```
How do I find out whether the registration was successful?
{
if (RegisterPasswordInput.text == RegisterPasswordRepeatInput.text)
{
// Rufe die asynchrone Methode auf und warte auf ihr Ergebnis
Task signUpTask = SignUpWithUsernamePassword();
// Warte, bis die Aufgabe abgeschlossen ist
yield return new WaitUntil(() => signUpTask.IsCompleted);
if (signUpTask.IsFaulted)
{
// Handle error
Debug.LogError("Registration failed: " + signUpTask.Exception);
}
else
{
// Handle success
Debug.Log("Registration successful.");
}
}
else
{
Debug.LogError("Passwords do not match.");
}
}```
https://docs.unity.com/ugs/en-us/manual/authentication/manual/platform-signin-username-password
assuming this is what you are using, it seems like it will not throw an exception if sign up was successful
Put code where it says "handle success"
private IEnumerator RegisterUser()
{
if (RegisterPasswordInput.text == RegisterPasswordRepeatInput.text)
{
// Rufe die asynchrone Methode auf und warte auf ihr Ergebnis
Task signUpTask = SignUpWithUsernamePassword();
// Warte, bis die Aufgabe abgeschlossen ist
yield return new WaitUntil(() => signUpTask.IsCompleted);
if (signUpTask.IsFaulted)
{
// Handle error
Debug.LogError("Registration failed: " + signUpTask.Exception);
}
else
{
// Handle success
Debug.Log("Registration successful.");
}
}
else
{
Debug.LogError("Passwords do not match.");
}
}
how do i make an onject always look at another object
transform.LookAt
I have tried it but it doesnt work correct. It give always success when the request did work!
Sounds right to me
I want when register was success
throw the exceptions if you want the task to end up faulted
transform.LookAt = player.transform.position; would this work
no. did you even bother looking at the docs for it?
no
that should be the first thing you do when you learn about a method or property you don't know how to use
mb ive never lookd at the docks
how can i make it so after the reGuy gets to green guy it stops otherwise when the greenGuy gfoes to -5-5-5 the redguy does too
ig i can do
if(greenGuy.transform.position == new Vector3(-5, -5, -5)
nvm
i can make an empty and have it teleport to that
hello, I'm trying to connect UnityEvent with argument, like this:
private void OnEnable()
{
for (int i = 0; i < lampSwitches.Length; i++)
{
int id = i;
InteractiveLight lampSwitch = lampSwitches[i];
lampSwitch.onSwitchToggled.AddListener(delegate { OnLightSwitched(id); });
}
}
How do I disconnect it?
private void OnDisable()
{
for (int i = 0; i < lampSwitches.Length; i++)
{
InteractiveLight lampSwitch = lampSwitches[i];
lampSwitch.onSwitchToggled.RemoveListener(delegate { OnLightSwitched(i); });
}
}
this doesn't seem to work. The more I enable and disable it, the more UnityEvent is invoked.
keep the reference
how do I keep the reference? what is the type of the... delegate thing?
Will need to put it in a list or an array.
where are the onSwitchToggles invoke? i think you can just call OnLightSwitched directly in there to prevent memory leak
If there's no other listeners you can use RenoveAllListeners, otherwise you can store the delegates in a list or dictionary and unsubscribe them later
Im trying to have something bounce off a wall, and Im worried if I just grab its "_rb.velocity" it might do weird things on the bounce(since it already "hit" the wall), is there a way to grab the velocity from the prevous frame?
inside the InteractiveLight itself. I'm not sure what you meant by calling OnLightSwitched directly.
the InteractiveLight doesn't know it's own id.
hmm after reading the linked article, I'm... not sure what can I implement.
or should I just always keep track of prevous velocity in a variable
You could store it in FixedUpdate.
Alternatively use RelativeVelocity from the collision
That should work, luckily there isn't any. Will still need more sophisticated solution for the future.
thanks...just realized Im using a trigger rn so have to redo all my plans anyway 😄
To get realistic bounces with a trigger you'll need to do boxcasts or SphereCasts
why box/spherecasts over just a raycast?
Can somebody help - i need the local forward vector from a gameobject. Because even when i use rigidbody.transform.forward it moves kinda strange because the animator das not know.
This should for a strafing behaviour
public override void MoveUnit(float movementSpeed)
{
if (unitLocomotionHandler.MovementInput == Vector2.zero || !unitLocomotionHandler.AcceptMovementInput)
{
return;
}
Vector3 localForward = rigidBody.transform.worldToLocalMatrix.MultiplyVector(rigidBody.transform.forward);
Vector3 localRight = rigidBody.transform.worldToLocalMatrix.MultiplyVector(rigidBody.transform.right);
Vector3 movement = unitLocomotionHandler.MovementInput.y * localForward + unitLocomotionHandler.MovementInput.x * localRight;
Debug.Log(rigidBody, rigidBody);
Debug.Log(localForward);
movement.Normalize();
Vector3 newPosition = rigidBody.position + movementSpeed * Time.deltaTime * movement;
rigidBody.MovePosition(newPosition);
}
public override void RotateUnit(float rotationSpeed)
{
if (!unitLocomotionHandler.AcceptRotationInput)
{
return;
}
Quaternion targetRotation = Quaternion.LookRotation(npcSteeringMovement.GetTargetPosition() - rigidBody.position);
targetRotation.x = 0f;
targetRotation.z = 0f;
rigidBody.rotation = Quaternion.Slerp(rigidBody.rotation, targetRotation, rotationSpeed * Time.deltaTime);
}
Try without the worldToLocalMatrix
just Vector3 localForward = rigidBody.transform.forward
To better fit the shape of your projectile, resulting in a more realistic collision
Local forward is always Vector3.forward.
The object's World space forward is transform.forward
Why are you messing with Quaternion x and z components
That's not how any of that works
They're not euler angles
alright but here you can see when i am standing in the direction from the npc like (0,0,1) than it behavious fine but. but when i am standing in its (0,0,-1) direction it gets weird
Vector3 currentDirection = _rb.velocity;
currentDirection = Vector3.Reflect(currentDirection, detectFrontNormal);
_rb.velocity = currentDirection;
``` so this will "deflect" the correct direction for speed, how would I make sure to not (instantly) rotate to be facing the new way Im moving?
Because you're doing really weird shit with the quaternion
oh really? because i just wanted it to only rotate on the y axis
quaternions are not euler angles
you should never be looking at the xyzw of a quaternion
pretend they don't exist
they don't mean what you think they mean
man those quarternions all the time - they black magic 😄
Vector3 direction = Vector3.ProjectOnPlane(npcSteeringMovement.GetTargetPosition() - rigidBody.position, Vector3.up);
Quaternion targetRotation = Quaternion.LookRotation(direction);```
float angle = Mathf.Atan2(rb.velocity.y, rb.velocity.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0, 0, angle);
should I be doing math like this or is there a nice function that already does this
transform.right = rb.velocity;```
lemme try
In general if you want to handle quaternions, convert them to Vector3 before if you really need to edit them:
// Vector3 to Quaternion
Quaternion q = Quaternion.Euler(0, 0, 0);
// Quaternion to Vector3
Vector3 v = q.eulerAngles;
I'd discourage that
euler angles are just sucky
Just learn how to use the Quaternion API
ignore the inner workings of them
and they work beautifully
Yeah i know, but sometimes its just easier / quicker to test
It only works if you treat all 3 euler angles as a set though. People try to do that and then isolate one of the axes
and that doesn't work
because euler angles are all interdependent on each other
it sometimes works, if you're lucky
Yeah i remember the head-scratcher when I first came into contact with that 😄
hmm so i tried it with
public override void RotateUnit(float rotationSpeed)
{
if (!unitLocomotionHandler.AcceptRotationInput)
{
return;
}
Vector3 direction = Vector3.ProjectOnPlane(npcSteeringMovement.GetTargetPosition() - rigidBody.position, Vector3.up);
Quaternion targetRotation = Quaternion.LookRotation(direction);
rigidBody.rotation = Quaternion.Slerp(rigidBody.rotation, targetRotation, rotationSpeed * Time.deltaTime);
}
but still the same behaviour. FYI the MovementInput Vector comes from
private void SetMovementInputDirection()
{
if (navMeshPath == null || navMeshPath.corners.Length == 0)
{
return;
}
// if the npc is close to the target position, stop moving
if (Vector3.Distance(npcMainManager.UnitMainManager.transform.position, GetTargetPosition()) < StoppingDistance)
{
npcMainManager.UnitMainManager.UnitLocomotionHandler.SetMovementInput(Vector2.zero);
return;
}
Vector3 direction = (currentPathPoint - npcMainManager.UnitMainManager.transform.position).normalized;
if (!isRunning || npcMainManager.UnitMainManager.UnitLocomotionHandler.MovementModeState == Unit.Animation.LocomotionState.Directional)
{
direction = direction.SetMagnitude(0.5f);
}
npcMainManager.UnitMainManager.UnitLocomotionHandler.SetMovementInput(new Vector2(direction.x, direction.z));
}
but that should not matter
well yeah are you talking abotu the movement or the rotation
because I just did the rotation bit
but thats all for the strafing behaviour but when it is comming to its true directional movement it works fine
/// <summary>
/// Moves the rigidBody based on the movement input in true directional movement in local space.
/// </summary>
/// <param name="movementSpeed"></param>
public override void MoveUnit(float movementSpeed)
{
if (unitLocomotionHandler.MovementInput == Vector2.zero || !unitLocomotionHandler.AcceptMovementInput)
{
return;
}
// Calculate the forward vector based on the Rigidbody's transform
Vector3 forwardVector = rigidBody.transform.forward;
forwardVector.y = 0f;
forwardVector.Normalize();
// Calculate the movement vector using the forward vector and movement speed
Vector3 movement = movementSpeed * Time.deltaTime * forwardVector;
// Move the Rigidbody's position using MovePosition
rigidBody.MovePosition(rigidBody.position + movement);
}
public override void RotateUnit(float rotationSpeed)
{
if (!unitLocomotionHandler.AcceptRotationInput || unitLocomotionHandler.MovementInput.magnitude == 0 || npcSteeringMovement == null)
{
return;
}
Vector3 targetDirection = npcSteeringMovement.currentPathPoint - rigidBody.position;
if (targetDirection == Vector3.zero)
{
return;
}
Quaternion targetRotation = Quaternion.LookRotation(targetDirection, Vector3.up);
targetRotation.x = 0f;
targetRotation.z = 0f;
if (rigidBody.rotation == targetRotation)
{
return;
}
// Rotate the Rigidbody towards the target rotation
rigidBody.rotation = Quaternion.Slerp(rigidBody.rotation, Quaternion.Normalize(targetRotation), rotationSpeed * Time.deltaTime);
}
Quaternion targetRotation = Quaternion.LookRotation(targetDirection, Vector3.up);
targetRotation.x = 0f;
targetRotation.z = 0f;```
you need to delete these last two lines
they are nonsense
Again if you want to rotate only on the y axis you do:
targetDirection = Vector3.ProjectOnPlane(targetDirection, Vector3.up);```
then you can use LookRotation
ahh good!
you also don't need to do Quaternion.Normalize(targetRotation)
(although you DID need to do that when you had the targetRotation.x = 0f; stuff)
ahhh alright
i really messed up here 😄
i think i know where the "bug" is
Vector3 movement = unitLocomotionHandler.MovementInput.y * rigidBody.transform.forward + unitLocomotionHandler.MovementInput.x * rigidBody.transform.right;
Because the MovementInput is like the direction vector towards the target. So when i am standing on Position like Vector3(0,0,20) and the npc on Vector3(0,0,0) and looks to me with the rotation Rotation(0,0,0) then it is kinda fine. But when i am Vector3(0,0,-20) and the npc rotation is then Rotation(0,180,0) it gets messed up.
and the other problem would be then that the MovementInput Vector will also be used for the animator. So it walks "forward" the animator get for its vertical -1
public override void MoveUnit(float movementSpeed)
{
if (unitLocomotionHandler.MovementInput == Vector2.zero || !unitLocomotionHandler.AcceptMovementInput)
{
return;
}
// Calculate the movement vector using the MovementInput and the transform's forward and right vectors
Vector3 movement = unitLocomotionHandler.MovementInput.y * rigidBody.transform.forward + unitLocomotionHandler.MovementInput.x * rigidBody.transform.right;
movement.Normalize();
// Calculate the new position using MovePosition
Vector3 newPosition = rigidBody.position + movementSpeed * Time.deltaTime * movement;
rigidBody.MovePosition(newPosition);
}
so looks like i need to seperate the MovementInput and the Values for the Animator. in the movement case. Because the goal was overall to have the same systems for ai and player so i dont need to write twice as much
and could easily controll a "npc" tooo
specifying an Array[2] is going to be more efficient then creating a List that will always hold 2 items correct?
yes
great
it is mostly faster by accessing elements, but lists are faste by adding and removing
So I can see that when I am testing in Play mode in the Editor and I have an Animator component that drives all animation of a UI...the animation restarts whenever I give focus back to the Play window making it neigh-on impossible to properly debug. What do I do instead? Do I switch all my Animator components out for Timeline or?
does Array[2] create an array that can hold 2 items or one that can hold 3
because indexing
- The capacity is always 0-Index Max + 1
Just like how Max Index is always capacity - 1
woah why cant I type the letter k
literally 1984
can I do ok?
ok
cool
great
swell
ill shut up now
How needlessly aggressive 😅
public class ColliderDetectorBullet : MonoBehaviour
{
private Bullet bullet;
BoxCollider2D groundedBox;
private void Awake()
{
bullet = GetComponent<Bullet>();
groundedBox = GetComponent<BoxCollider2D>();
groundedBox.enabled = false;
}
private void Update()
{
DetectFront();
}
[SerializeField] LayerMask mask;
public void DetectFront()
{
Vector2 position = transform.position;
position.x += groundedBox.offset.x;
position.y += groundedBox.offset.y;
RaycastHit2D[] hit = Physics2D.BoxCastAll(position, groundedBox.size, 0, Vector2.zero, 0, mask);
if (hit.Length > 0)
{
bullet.detectFront = true;
bullet.detectFrontNormal = hit[0].normal;
}
else
{
bullet.detectFront = false;
bullet.detectFrontNormal = Vector3.zero;
}
}
}```
its not hitting my wall for some reason...and its only this wall also, the wall facing the other way works fine
is something in my code wrong so the cast is like "facing" the wrong way?
Yeah your Lerping the wrong way.
https://gamedevbeginner.com/the-right-way-to-lerp-in-unity-with-examples/
If only one wall is the problem
How can I lerp the right way haha
i still access the array the same way as a list, right
(im not used to arrays I usually just use lists)
Yes.
okay
A list is just an array that gets resized
appears 1 side of the wall is the issue
meaning something with my code here is likely wrong