#archived-code-general
1 messages ยท Page 390 of 1
Working for me
Oh wait
I see it when x is 90
I think you're just experiencing gimbal lock
This is the problem with the euler<>quaternion conversion and gimbal lock basically
is there a way to represent rotation without Quaternion or to have something be converted to it?
I usually just use an empty GameObject
You can just use a Vector3 too
for euler angles
true. looks the same in the inspector
If you're doing 3D, I suggest just learning AngleAxis and running that in OnValidate
If you're running into gimble
Basically yeah the problem is the conversion from eulers -> Quaternion -> eulers that the inspector does for quaternions
Since euler angles aren't unique
ill try to use a Vector3 and see how it goes
https://hatebin.com/wpbfhbbgtq
Some rotational orderings you can play around with. The way it's done in the editor (Eulers) I believe is ZXY ordering
^ Can convert it to onvalidate but was using to automate it for some testing
its okay, using a Vector3 and passing it into Quaternion.Euler worked
thanks for helping :>
How to set animations on the character from C# components(2D)?
Depends on what you're using for animations...
It's the default Animation, Animator and Animation Clip classes
Sprite animations
But I can't find how I can switch the state from outside
Like there is no function like SetState("Idle") to force the state back to idle
There is Play tho
In the very doc you just linked
I usually use parameters and transitions though
Thank you
Yeah I missed it and was confused how to do it then
I wanna do a full state machine for the character to separate the logic in different states:
Show your Support & Get Exclusive Benefits on Patreon (Including Access to this project's Source Files + Code) - https://www.patreon.com/sasquatchbgames
Join our Discord Community! - https://discord.com/invite/aHjTSBz3jH
In this Unity tutorial, We'll use, from the ground up, the State Machine programming pattern to setup some simple logic for o...
To avoid the parameters/flags and checks hell
And just play the animation when character enters the state
wdym, there's not really a hell for that
Are you using state machine behaviours?
Nope
at the most direct, basic level, you could send a trigger for changing state, so you can use the animator tree to manage transitions correctly
having a state machine is a separate idea from using transitions in the animator
you can do both, one or the other, or neither
So you have a C# statemachine? Or are you using the animator for that too
How can I have a public property (as opposed to a field) exposed in the inspector?
C# state machine. But I'm using a default animator.
use the [field:SerializeField] attribute
(you can ctrl+z in the message box to restore your message)
Ah, I see: https://docs.unity3d.com/Manual/StateMachineBehaviours.html
So I can do things when the animation is played. Yeah, that's the main reason I wanted to make my own. But I guess I can get away by using the behaviors and use the built-in one.
That is up to you
If the animator provides all the functionality that you need for state machine then sure
Hey all, general programming question here geared at C#. Let's say you have a base class with a virtual method that returns a bool on whether it was successful. Then I inherit from that class and override that method, using the original base method's logic, but wanting to add onto it additional failure scenarios in the override method. What is the best way to determine if the base method succeeded before I bother processing the child method's logic?
Check the return value of the base method.
Oh? Sorry how do you do that?
an if
public override bool DoTheThing()
{
bool parentDidTheThing = base.DoTheThing();
bool childDidTheThing = stuffToDo <= stuffDone;
return parentDidTheThing && childDidTheThing;
}
well, you would check for a failure in the base method before doing any of your own logic
You might, if the only thing the method does is check. If you want it to do some stuff anyway, and the return whether or not it's done, you might want to run it regardless of whether the base method failed
I don't know why I was struggling with that so much lol. I feel silly now it was a rather simple and obvious solution, but for whatever reason it didn't occur to me and when I googled it people were saying it can't be done and I was like...no way
Thought for later that just struck me like lightning;
I wonder if there would be any major downsides to just... Using bones to drive animated behaviors.
Like, having a "Gun Bone" that just floats over in the corner, and when its Y Value is set to 1, a held gun fires.
Am I crazy, or is that a thing that people do
This sounds like something you'd rig up in Blender
But it does not make any sense when you can just write code
If you want something to happen at a specific point in an animation, that's what animation events are for
I love how concise you can make C#, going from
if(Input.GetMouseButton(0))
{
if(MenuEvents.SelectedBrush == 0)
{
brushState = 1f;
}
else if(MenuEvents.SelectedBrush == 1)
{
brushState = -1f;
}
}
else
{
brushState = 0f;
}```to
```cs
float brushState = Input.GetMouseButton(0) ? (MenuEvents.SelectedBrush == 0 ? 1f : -1f) : 0f;```
I always wonder how far C# can actually be pushed to make stuff short like that
You can get a little too clever..
public override Vector3? Destination => brain.entity.TryGetPerception(target, out var perception)
? perception.DispersedLocation
: null;
oh absolutely
After pushing and then cloning the project, when I open it in new place with the same editor, I get a
Assets\Scripts\CharacterMovement.cs(21,12): error CS0246: The type or namespace name 'InputActionReference' could not be found (are you missing a using directive or an assembly reference?)
Did the Input System package get installed?
You can check in the package manager window
Apparently, it didn't. How do I make it get installed automatically then?
What version control system are you using? Git?
Yes
the first thing I discovered like that, was how you can write strings like
$"The dice rolled {diceValue}, you have {goldAmount} in the bank"``` instead of the much (imo) uglier ```cs
"The dice rolled " + diceValue + ", you have " + goldAmount + " in the bank"```
did you put the entire Packages folder into your .gitignore?
It sounds like the package manifest is not being version controlled
Oh yeah, I love string interpolation
It's significantly tidier
$"Oh god it broke: {oopsPercentage:P0}"
mhmm, its saved me a lot of headache over the years
it was only when I looked at a mess of "blah blah" + value + "blah" + value + "blah" + value + "blah blah blah" I was sure you could write it better
it was only when I saw some C++ code which had a very odd way of writing strings, that got me thinking
sprintf?
yum
Check if /Packages/manifest.json is being version controlled. If not, then you'll have problems!
If you need a good .gitignore, you can use https://github.com/github/gitignore/blob/main/Unity.gitignore
Is there a way to expand a TMP_Dropdown via code?
its something like "you have %x gold and %d health", x:goldValue, d:healthValue, but thats definitley incorrectly written
(format strings are pretty common, and even interpolated strings like in python or c# have format-string-like format specifiers)
yep that's a format string
I think C# has a something similar where the parameters come after a string, ive never needed to write strings that way though
This gets called by OnSubmit and OnPointerClick, both of which are ways to open the dropdown
Yeah, you can pass it a format string and then a list of parameters
well, an array of parameters -- it uses the params keyword
char buf[51];
snprintf(buf, 50, "you have %d gold and %d health", goldValue, healthValue);
whats the use case for it?
You might not know the format string ahead of time
i really love/hate c's thing with method pfxs/sfxs lmao
String interpolation demands that the format string be a compile-time constant
I'm pretty sure that everything compiles into a String.Format call eventually, too
Too bad we can't have https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/interpolated-string-handler in Unity because C# 9.
There should be a "collection of little tricks and fancy features that make life a little easier" for C#, there's a lot of little things that I've found over the years and even now I still occasionally learn something new
I just found it, yes, it is in .gitignore. I found it on the internet and the comment says:
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
That might be talking about NuGet packages
What does that mean. Nuget packages restore? But how would it know which to restore?
when I search up "package restore", I get lots of people talking about NuGet
which is an unrelated package manager for C# packages
I use "NuGet for Unity", so I have some assemblies in my project provided by it
I have that specific folder ignored, but not every folder named Packages
fwiw you should be using this https://github.com/github/gitignore/blob/main/Unity.gitignore
which does not ignore /Packages
yeag
/Packages is also where you put "embedded" packages
you can copy things out of the library's package cache to embed them in your project so you can make changes
ooh, it runs in the editor
also, one little suggestion for the .gitignore
pretty much the same for me ๐
I also include:
*mono_crash*.json
*mono_crash*.blob
.DS_Store
*.blend1
*autosave*.spp
The first two are for crash logs
and then you've got good ol' DS_Store and some autosave files
Ok, thanks.
That should fix it
oh that's weird, i swear it used to include .DS_Store
I also exclude the file that includes my steam password 
When I create a server build of my game, run it, then press Ctrl + C or close the console window, will Unity still perform its cleanup (like OnDestroy) like it would when I close the window in a client build?
SIGINT is pretty gentle. I'd expect it to shut down normally
It should, yes.
Hi, I'm new here. Where do I ask for help with writing code? There's something I need help with in my project
Here or #๐ปโcode-beginner
Thanks
Okay, thanks for the quick replies!
You can double check by seeing if Application.quitting fires.
[RuntimeInitializeOnLoadMethod]
static void Test() {
Application.quitting += () => Debug.Log("Quitting!");
}
I'm currently working on my PlayerController for a 2D platformer and I'm trying to make an acceleration/deceleration movement style similar to classic Sonic. I have the acceleration part down but the tutorial I followed didn't go into deceleration. How do I show my code?
If I were you I would make it into a method since properties should not get too complex. In your case it calls a method and this is often not expected
Though you seem to override something so maybe that's not possible...
!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.
Calling a method in a property seems perfectly normal :p
The important thing is that it doesn't cause a change in state
That would be very surprising
Very true
Just that properties are generally not assumes to be complex in any way
Or depending on other data apart from simple data
I already have some logging on cleanup so I think I'll just check the log file after I quit the program since the console window closes instantly when it's done running.
Thank you! Here's the relevant code
[SerializeField] float jumpForce;
public float accelerationSpeed;
float moveSpeed = 0f;
float maxSpeed = 1000f;
float HorizontalInput;
Rigidbody2D rb;
void Update()
{
HorizontalInput = Input.GetAxis("Horizontal");
if (HorizontalInput != 0f && moveSpeed <= maxSpeed)
{
moveSpeed += Time.deltaTime * accelerationSpeed;
}
if (HorizontalInput == 0f)
{
moveSpeed = 0f;
}
}
private void FixedUpdate()
{
rb.velocity = new Vector2(moveSpeed * HorizontalInput * Time.deltaTime, rb.velocity.y);
}```
i think AddForce should give you the movement you are looking for
if you want to decelerate at the same rate, you could just do moveSpeed -= for the opposite effect as the the acceleration
although i dontยดt recommend using Addforce every frame.
if you want a different rate, you could do the same with a separate coefficient
I tried that, but it just kinda stores the velocity I already built up
wdym by that?
that doesn't make sense
well, you wouldn't use AddForce(rb.velocity) or something
let me check again
You'd apply a steady amount of force in each fixed update.
one main problem you have is your code is not even differentiating between the player holding Right or Left on the keyboard or joystick
alternatively, you could achieve the effect with physics; use AddForce to apply acceleration, and then let linear drag/friction handle deceleration
it's just saying "Is horizontal input not zero? If so, accelerate to the right"
So even if you hold left here, you will go right
it's being multiplied by the input when the velocity is set
oh
that's... weird
which wouldn't work for controller input, but for button input it works even though it doesn't make sense semantically
No actually, since when you hold left the value is -1
no, when you go left the value is between -1 and 0. -1 is just the maximum magnitude
Yes I understand that I just didn't see it's being included in the last line
yeahi guess he is doing this so he can use it inside FixedUpdate
The problem is that if you switch from left to right, you'll keep your move speed
which is totally fine
Consider the following
float target = maxSpeed * HorizontalInput;
float maxDelta = Time.deltaTime * accelerationSpeed
moveSpeed = Mathf.MoveTowards(moveSpeed, target, maxDelta);
instead of keeping a moveSpeed, you should keep a moveVelocity and let opposite inputs decelerate and then accelerate in the opposite direction
You can also store a velocity, yes
(well, I'm also storing a velocity -- note how moveSpeed in my code can be both negative and positive! I'm just storing the X velocity)
I tried it again, the problem is that it seems like the moveSpeed is being decreased at the same rate as it increases when the button is being held so the result is that the speed doesn't hit 0 nearly fast enough
so write some code to change that
you'll need a bunch of if statements
I will say Input.GetAxis in this kind of code is a problem, because it's adding an unaccounted-for extra layer of "acceleration" into all of this
then use a larger coefficient for decelerating
You should use GetAxisRaw
Here's what I did
if (HorizontalInput != 0f && moveSpeed <= maxSpeed)
{
moveSpeed += Time.deltaTime * accelerationSpeed;
}
if (HorizontalInput == 0f)
{
moveSpeed -= Time.deltaTime * (accelerationSpeed * 2.5f);
if (moveSpeed < 0f) moveSpeed = 0f;
}
if (Input.GetKeyDown(KeyCode.Space) && (isOnGround))
{
rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}```
Right now my character just kinda stops, no momentum is carried over
this code has nothing that actually moves the character side to side
surely you omitted something
Sorry I didn't share everything
{
rb.velocity = new Vector2(moveSpeed * HorizontalInput * Time.deltaTime, rb.velocity.y);
}```
The parts I shared previously are specifically under Update. Sorry, I'm still new to this whole code sharing thing so I didn't think those parts were relevant
Well yeah see how you're just directly feeding HorizontalInput into the velocity?
Using GetAxis was the ONLY reason you had any acceleration at all
If HorizontalInput here is 0... well you're multiplying by 0
make sense?
(uh no moveSpeed was also increasing over time before...)
Yup that's still the same as before
Sorry I meant only reason there was acceleration when input was 0 before
Ooooooh that makes sense yeah
Because GetAxisRaw goes directly from 0 to either 1 or -1 so now when I let go of the button the velocity just becomes 0 instantly
this all seems overcomplicated. Couldn't you just do something like
float hVel;
float maxSpeed = 5;
float accelerationSpeed = 4;
void Update() {
float targetSpeed = Input.GetAxisRaw("Horizontal") * maxSpeed;
hVel = Mathf.MoveTowards(hVel, targetSpeed, accelerationSpeed * Time.deltaTime);
rb.linearVelocityX = hVel;
}```
What does Mathf do? I haven't learned that yet
Mathf is a class that contains a bunch of math utility functions
it doesn't "do" anything
MoveTowards does this: https://docs.unity3d.com/6000.0/Documentation/ScriptReference/Mathf.MoveTowards.html
I use MoveTowards quite frequently
the only thing left to do is vary which accelerationSPeed you feed into MoveTowards based on whether the target direction is aligned with or opposed to the current horizontal velocity
That sounds easy enough
Are you guys pooling your audio sources in your sound managers?
Or is the benefit miniscule compared to just making and destroying audio sources for sfx
I recommend pooling anything that is a UnityEngine.Object and enabled/disabled frequently
That does make sense I suppose. But then how do you know if a sound is finished so you can put it back in the pool?
@river kelp The simplest way would be to make a coroutine/awaitable, but a more performant way would probably be to keep track of all the playing AudioSources in your sound manager
And then intermittently check if they are still playing?
I wish AudioSource had events like OnStop :/
Or, do I even need to "return them to the pool" in that sense?
Something like that
I haven't implemented it, just throwing ideas. I normally use FMOD
You could yes
Using the Playables API to play audio might be something to look into ๐
Hmm. I haven't looked into stuff like FMOD, how much hassle is it compared to the value?
Assuming sound is fairly important to my game, would you recommend taking the time to implement FMOD over making my own custom sound manager?
(Also, FMOD is free, right?)
I can't really give a good comparison because I have used FMOD instead of the default audio for as long as i remember
For indies yeah https://www.fmod.com/licensing
Currently trying to make a string for a TMP UGUI component that highlights some lines conditionally. For some reason, this spits out Input string was not in a correct format
testimonyContents += $"{(pageIndex == Convert.ToInt32(selectedPlant[4])? "<#FFFF00>" : "")}<u>{ts.speaker[pageIndex]}:</u><space=1.5em>{ts.dialogue[pageIndex]}";```
But for some reason this works fine. ```C#
testimonyContents += $"<#FFFF00><u>{ts.speaker[pageIndex]}:</u><space=1.5em>{ts.dialogue[pageIndex]}";```
It does look like FMOD does a lot of what I am trying to develop myself
I usually like to make my own systems but I haven't ran into any limitations with FMOD yet
I'd say try it out ๐คทโโ๏ธ It's pretty intuitive especially if you have used DAWs
And you can control pretty much everything from C#
I've been burned by very excessively advanced/generic asset store assets before, with lots of feature bloat etc. Do you think that applies to FMOD?
no
FMOD isn't an "asset store asset". It's a "proper" piece of middleware, with an asset store asset
Yes, but that doesn't really answer my concern
it's professional middleware, it's one of the two go to sound solutions for games
I guess I'll give it a shot, thanks
I guess I've never gotten far enough in sound design to mess with such things but what's the "deal" with FMOD? What does it replace exactly and why would you want/need to replace it? Does it replace AudioSource(s) entirely?
Haven't used it, same as you. Just been aware of it for years - @hexed pecan is the many to ask.
it decouples sound design from the game itself
so you expose events and parameters and then your sound designer can react to those in fmod studio and your game uses that data to do sound stuff
So do you include stuff like listener position and sound source position in those events?
unity's core stuff doesn't do much more than 'play this sound', but fmod has support for stuff like blending dynamic sounds based on parameters in realtime
That does kind of sound like a lot of work to set up though
How easy is it to just "play sound"
maybe if it matters? I think there are a bunch of ways to do it
it comes with some components that bridge their stuff into unity
you can do it in one line, but yeah only once youv'e set up fmod to include that sound
that's an advantage if you have a sound designer who can be in charge of that stuff
and if you need dynamic audio
pletny of games are just playing 1) some music and 2) oneshot sound effects, so you probably don't need it
Despite having no sound designer I've kind of painted myself into a position where I have to become one
Indie game devs have to wear so many hats
but there are a lot of little things with sound design that you end up layering in, like limiting a particular sound when it's triggering too much (or replacing it with a different one), or ducking particular sounds in favor of others, etc. that it's nice to have supported already for when you need them
So my choices are really code and make a sound manager myself
Or include one like FMOD. I was just dipping my toe into it when I came here for advice
if you are just starting off, I'd just make a little class to manage sounds and let you play them
No like, I was past that and just getting into the "This isn't working I need a proper sound manager" so I was just starting the code for that
what would make it 'proper'
Well now I have a bunch of components with direct references to audio clips in the prefabs and awkward code referencing one of several audio sources on each object
you should probably centralize it
How can i increase the fps of my game for android? the fps is fine on IOS and web but on android it's very less.
its a webgl 3D game
As opposed to a pooled sound manager I can ask to "PlaySoundAtLocation("thump1", transform.position)" or whatever
One of the benefits of FMOD is not needing gameobjects to play audio
Yeah that's what I was starting on
Better performance overall afaik
that seems fine to me for starting out
Good UI for editing automation/modulation curves
increasing FPS is done by optimizing your game. Use the profiler and go after things that are slow/inefficient
you'll find things that you want and over time can decide if you need something full-fledged or should just progressively add the little things you need
Yeah but I already had issues with for example sound repetition / picking sounds out of a group
What's the learning curve like for FMOD
Like, random footsteps type stuff
yeah, I mean if you're already needing that, go for it
This is my only hangup too really. I'm wondering if it's worth learning a full system
but none of that is so complex that it would take long to do your own version and that would probably be valuable
I did do that. But for android it still remains the same.
Is there a way i can use the profiler on android web?
and certainly faster than learning fmod
not sure, I've only really dipped my toes in
I picked it up pretty fast but I was already familiar with a lot of audio softwares
it seems pretty easy to get started but like anything fully featured, there's a lot of stuff in there that can be overwhelming
I still keep discovering new features tho
I guess, but I'm already learning normal audio editing to do a lot of the things I was hoping Unity could do out of the box, like Unreal can.
Like layering audio reasonably
I miss the audiograph...
I have like a few hours experience with Audacity and some days experience with Unity's AudioMixer stuff. Am I going to be missing a ton of context that many audio software(s) have?
I have more than a few hours in audacity and fmode still confuses me
Maybe there are some terms you might not know, but the logic is pretty intuitive for me at least
You control stuff with parameters similiar to unity's animator
And any knob can be linked to a parameter or a curve
How much clutter will I get in my version control? And will other developers also need it to run the game?
I do remember getting some feedback in a school project about cluttering the project with FMOD files years ago lol
Like will I need to teach my artist how to work with this too or
But that was just my poor folder management
Does your artist handle audio? ๐ค
No
I'm just wondering if he needs to install and run this to run Unity if I start using FMOD on my end
anyone who you want to edit audio stuff will need fmod studio yeah
Like, what's the requirement for other developers to run a project with FMOD in it. Maybe I'm confusing what Fmod is?
but only sort of, they can use the existing stuff from within unity if the events are already setup
Oh they don't need standalone FMOD just to work on the unity project
So they just need the package, basically?
You build banks out of FMOD into your assets folder
Yeah the project needs the package/plugin
And FMOD comes with components for playing sound and whatnot?
So essentially for non-sound designer devs it's just a replacement set for the audiosource / audio listener type stuff
Yes, most of the unity components have their FMOD equivalents
Although I usually just do everything from C#, except for the listener component ofc
Sorry for taking up so much of your time here, you've been very helpful, but could you perhaps show me a line for what playing a simple sound effect would be like?
Using FMOD?
RuntimeManager.PlayOneShot(eventReference, position)
Or create an instance with CreateInstance and do whatever you want with the event
eventReference here being a reference to something that, on the FMOD side, plays sound?
For example a FireGun event
the thing is, you're now working at a higher level of abstraction, so you don't 'play a sound', you 'trigger an event' which you configure a response to in fmod
right
And then I configure these events and tie them to sound in FMOD studio
which creates a "bank" in my project
in the inspector, you have components like this
and you can select the event from a dropdown cause it's linked to fmod and knows which ones you've made
so I don't actually need FMOD studio to run the game
as well as adjust parameters
no, of course not
fmod studio is a tool for making your game
once the game is compiled, none of this matters
That would be like needing blender to run the game
Sure it wasn't a question it was just like, mentally going through what I have learned
the exported "bank" in my game is why I don't need fmod studio, is what I meant
Thanks for the help guys I'll dive into this and see what I can do with it
Is there any real harm in having a class not derive from monobehavior, when the class is still making use of the Unity namespaces?
public class RectShape
{
(GameObject A, GameObject B) _handleObjects;
public GameObject HandleObjectA => _handleObjects.A;
public GameObject HandleObjectB => _handleObjects.B;
public Vector3 HandleA_Position => _handleObjects.A.transform.position;
public Vector3 HandleB_Position => _handleObjects.B.transform.position;
public Vector2 Size => new(0f, 0f);
public Vector2 Center => new(0f, 0f);
RectShape(Vector3 a, Vector3 b)
{
GameObject handleA = new("HandleA");
handleA.transform.position = a;
GameObject handleB = new("HandleB");
handleB.transform.position = b;
_handleObjects = (handleA, handleB);
}
public static RectShape Construct(Vector3 a, Vector3 b)
{
RectShape newRectangle = new(a, b);
return newRectangle;
}
}```I doubt it actually matters, but still
MonoBehaviour is a very specific thing. It makes a component you can attach to GameObjects. If you're not making a Component, you don't derive from MonoBehaviour
cool, I figured that was the case. The code runs fine, I just wasnt sure if Unity had a specific expectation with the class
This is something I took a hot minute to figure out
You only care about Unity when you need Unity to do stuff for you, like letting you attach components to objects
You can do tons of stuff that has absolutely nothing to do with Unity at all
Itโs fine. Just note you need to use System.Serializable if you want any of the data in the inspector.
But its not a mono class, so it wont ever show up in the inspector anyway
components require MB dont they?,
it could as a field on an actual component
ah, got it
Indeed -- or it might show up in an asset somewhere, like a ScriptableObject-derived class
or you might want to serialize it with JsonUtility!
This threw me when I was first getting into C# and Unity, I assumed that it was only possible to work with a project when every single thing was totally intertwined with the Unity API. I basically treated it as if Unity was the most important thing when it came to every aspect of the code
Yeah.
I ascribed a lot of "magic" to Unity
e.g. when you destroy a unity object, it now equals null
but that ain't a null reference!
Unity can't somehow change the contents of your variable
Its why its so important to learn the language before attempting to use the engine (even though thats exactly what I did ๐ )
Imagine not knowing how to use constructors because you're too used to Unity's instantiation concepts
I think that was a problem for me
I know I had a lot of trouble trying to do certain things because if unity provided a method that wasnt quite right, what else are you meant to do?
funny to think that constructors once probably felt like some really advanced and complicated thing
one "oh you can do that huh" moment was learning that youre able to put multiple classes in the same file
you can also put one class in multiple files!
partial classes are a bit weird
I tried using them once because I had a horrific uber-class that was way too big
I then realized I needed to break that thing up completely
partials seem like a great idea with a lot of uses, but in reality they arent that great and have very limited usecases when they'd be worth it
I managed to chop the class into five pieces. I then had FIVE files that I couldn't find anything in!
Even worse than one file I couldn't find anything in
Now I have an Entity class and lots and lots of little modules to add features
I think when you see that Unity always makes the file name match the class, not realising it only does that because a template file, that might be why I assumed its one file per class
its only actually specific situations where the class and file name have to match, right?
scriptable objects or something break if theres a mismatch, that sounds right
They don't have to match anymore
It was a rule for a long time
However, you can't have more than one MonoBehaviour/ScriptableObject per file
Unity doesn't care about the name of the class or the contents of the file. It just knows that a component corresponds to a specific MonoScript
and MonoScript is the type of asset you get when you import a .cs file
I wonder what they were doing for it to be a rule
It does prevent a little bit of weirdness.
The "Add Component" menu uses the asset name, but the inspector uses the class name
Yeah, especially if its one MB class per file, if the name doesnt match the class, it would suggest somethings broken
partial classes are a common trap for newcomers, usually your classes are too big because they're holding many responsibilites and turning it into multiple partials wont solve anything
they do have some pretty cool use cases though, like Unity uses for DOTS code generation
yeah, they make sense for codegen
otherwise you're just rearranging deck chairs on the Titanic
partials feel like magic the first time you use them
the novelty that you can write the same class in 2 locations, without you needing to have the same code written out in both
#region is another thing that I dont actually know if its good or not
if you have a need for regions in your code, your code is probably too long and/ or poorly organised
never seen a good use case for that, it's usually either trying to hide messy code or giving you irrelevant information that could be derived from other sources
thats a criticism ive heard a lot
The 'clean code' book says to avoid them, IIRC
Yeah, that's my feeling
I have one big use for them: I put all of my debug-only stuff at the end of my classes
because I have fields that keep track of stuff like "show X in the debug overlay"
they're noisy and don't really matter anywhere else
e.g.
the one true rule is that there are no strict rules ๐
so it's best to understand why something is good/bad, instead of just knowing good/bad, because bad things can be good in some cases
my usual reason to use them is when I just want to divide stuff out into little chunks, when I dont feel the need to actually segment the code itself up.
or a constructor might go through 3 different steps, a lot of the time I'll just make 3 regions and even if they only have a few lines each, at the time it seems like a useful thing
in that case you could probably use a preprocessor directive and get conditional compilation for free
to me, theyre more like a fancy way to comment stuff out, into a section that I can collapse
group stuff up, add a nice heading, and now I can collapse that whole group in a function and the region name itself is like a comment
I still need this in the built game!
you can have custom directives though
sure, but if you're defining symbols that will never not be defined just for organization, then you've just reinvented regions
indeed
#if GAME_EXISTS
the anticipation is killing me! ๐
I can't recall a time where I've been reading through someone else's code and been glad it has regions. It usually feels like it clashes with my own mental map of the class and hides things.
It doesn't help that Rider automatically collapses all regions by default.
wait, why is Entity large?
Almost all actual game logic lives outside of Entity, but there's a fair bit of bookkeeping in there
e.g.
Actually, this class isn't one that's giving me too much trouble. It's pretty clearly organized
how many lines of code?
700, ignoring the very verbose IMGUI-based debug view
that is a bit on the high end, but hey... perhaps the splines or some other parts can be extracted to a module (or a "component" of sorts)
but some classes are just a bit larger sometimes, and splitting them doesn't really make anything better (especially splitting to partial classes ๐ )
Yeah, there's very little game logic in this thing
It mostly just keeps track of the entity's modules and calls methods on them at the appropriate times
It is responsible for tracking everything the entity has perceived.
I've been pulling more and more stuff out of it. It used to control a NavMeshAgent
now i don't require an agent at all
nice, small gradual improvements are โค๏ธ
I was using the navmesh for both moving around and some extra things, like finding a valid location to exist in
now that's abstracted into a Pather
...starting with NavMeshPather, of course ๐
๐ ๐
My Player and Monster classes used to be like 2-3 thousand lines long
I have way, way more code now, but it's much more spread-out
can URP can fps drop on android?
That question doesn't make sense. Anything can "fps drop" on Android.
The more you do, the more effort the device requires to do that thing, and if all the things combined are too much for the device, of course it will slow down.
it works fine on ios and web. but i see a lot of fps drop on android alone
that too on a bit low end device
Well, you can only profile it to find out why
Hey guys, I have a projectile (NetObj + rigidbody + spherical trigger collider) I am spawning in the scene and using FixedUpdate I am moving it through the air to hit another gameObject (NetObj, rigidbody + box trigger collider) both extrapolate interpolation and their Collision Detection is set to Continuous Speculative. Additionally, I set the timestep to 0.1.
Despite all these changes, in some instances, both the projectile and the box do not detect the collision. What am I doing wrong and how could I fix it?
the continuous collision detection stuff generally doesn't apply to triggers
Best to do your own manual SphereCast I would think
Oof, lol, that's gna be interesting. I wonder why unity doesn't provide an out of the box solution.
Anyway, I'll ask chatgpt. Any expert pointers?
You're starting a new coroutine every frame
mate, you've already been told not to crosspost. i also answered this nearly 20 minutes ago in #๐ปโcode-beginner
I thought I gave you a pointer.
Best to do your own manual SphereCast I would think
ooh
wats crosspost
Cool, I'll try that then. Thanks
posting the same question in multiple channels
ooh
On top of what praetor said, I dont think the interpolation mode here changes anything. The time step you set also wouldnt help if its only checking 10 times per second, and if the objects are moving decently fast
So games like Tarkov also rely on spherecast? Or would bullet sized objects require a more elaborate solution?
almost certainly yes.
I havent played tarkov, usually bullets can be done with raycast or spherecast if you want to simulate an object with radius
Yes to spherecast or the elaborate solution?
Hey, i want to create some sort of climbing, but in a way where you can just walk along any surface, so think you can walk on floors walls ceilings and meshes but when you're in freefall you'd fall to the ground. Can anyone explain or break down what kind of steps I would need to take to accomplish this? I'm sort of stuck on how I would create this system with edge cases like sharp corners or the curved sides of a ball where a simple raycast down wouldn't really work.
spherecast
Awesome, thank you ๐
You'll want to start by making a character controller that doesn't have any hard-coded directions in it
so, for example, it should not make you fall by doing velocity.y -= Time.deltaTime * 10;
note that the built-in CharacterController component doesn't let you rotate it, which could be an obstacle
right now I have a state machine running the movement, for the falling state I have the character rotate to be upwards from the ground, and falling in that direction. and for the climbing I just put it into the regular movement state since thats whats happening really. I have a raycast downwards that detects the hit normal to rotate the player. But i'm not sure what to do from there and like you said I had much trouble with the charactercontroller so i ended up removing it.
So you can properly move around on a plane at any orientation right now?
right now i have it rotating but idk how to move it tbh, my idea was to use Transform method to move it somehow according to the hit.point
You can construct a rotation out of a forward vector and an up vector
var rot = Quaternion.LookRotation(player.transform.forward, hit.normal);
var worldForward = rot * Vector3.forward;
e.g.
This would misbehave if you somehow wound up aligning the player's forward vector with the normal vector of the ground
URP was the problem. works better with built in rp
are there any optimal settings for URP?
Hi, how can I achieve something like the following image says?
Project the direction AP onto the red line direction vector
sorry, i couldn't understand, can you clarify a bit?....suppose p is player and it moves around the whole world...but there is a curve or path...and the green object will be clamped to that path only but will also follow the player along the path only...
How to get game object from inside of Animator behavior script?
In OnStateEnter(and some other callbacks) you get the animator reference. You get the object or any of it's components from there. Check the docs.
I did check the docs.
It doesn't say anything
So where in the docs does it say how to do it?
You're talking about the animator state machine behaviour, so check it's page, instead of the animator.
Doesn't say
It says it all. Have a look at the code sample on the page. And the specific methods I mentioned.
I'm not looking for animator and its components, I'm looking for the parent game object of the animator component and the components of that game object.
I know I can do animator.GetComponent but I want to find the parent game object of the animator and it doesn't say how to that in any of the pages that you said it does.
You can get the parent via the transform.
Because it's not related to animator at all. You can get the parent of the GameObject via the transform component. It's responsible for the object position in the hierarchy.
Have a look at the code sample on the page
using UnityEngine;
public class AttackBehaviour : StateMachineBehaviour
{
public GameObject particle;
public float radius;
public float power;
protected GameObject clone;
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
clone = Instantiate(particle, animator.rootPosition, Quaternion.identity) as GameObject;
Rigidbody rb = clone.GetComponent<Rigidbody>();
rb.AddExplosionForce(power, animator.rootPosition, radius, 3.0f);
}
override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Destroy(clone);
}
override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log("On Attack Update ");
}
override public void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log("On Attack Move ");
}
override public void OnStateIK(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log("On Attack IK ");
}
}
The code example shows how it creates a new game objects and gets its' component but doesn't show how to get the parent game object of the animator and then its' components.
It does show you that you can get the animator. An animator is a component, and as any component it has references to the GameObject and it's transform.
Look at the inherited properties of the Animator class
Then, there's also GetCompinentInParent, so you can make it just animator.GetComponentInParent<Type>()
Check the docs. It's all in there.
Thanks, yeah I checked the docs before asking here and scrolled through the properties and methods but missed it.
I also googled on how to do it and found multiple threads on the forum without an actual answer.
The closest thing that was recommended was animator.GetComponent but I doubt it gets the components on the parent game object, more like attached components to the animator.
As I said earlier. It's a pretty basic thing and largely unrelated to animator in a any way.
You can get a parent from a component with component.transform.parent and then use get component on it. This is pretty much just working with gameObjects and components basics.
What about just animator.gameObject?
That's the GameObject the animator is attached to, not it's parent.
Yeah, that's what I want: to get the game object of the mono behavior and the animator.
So like Animator is a component on a game object, and so I want to get the game object.
what you said did the job...but still one problem remains, the square in the vid is the player and the sphere is the objects that will follow...the object to follow is moving along the direction but still not aligning to the player
Not sure what you mean by that. How is it supposed to "align" with the player?
i mean along the x axis
So what's the difference between the parent and the object it is attached to?
I want to get the game object Animator is animating.
actually i will make a path for a audiosource to follow along the river while keeping the player aligned on the specified path...for example, the sphere should be in the red dot
The terms "parent"/"child" are used to describe relationships of Transforms (or GameObjects).
In this case you don't want the parent, you want GameObject that owns the animator component
I.e. the gameobject that the component is attached to
Might want to go over the basics of what gameObjects and components are and the relationship between them.
I'm still not sure what you mean. Is the green line - the path that you want the ball to follow along? Or the blue one?
Ah
I looked at the video again. Okay. I get the issue I think. So the ball needs to be on the same y position(in screen space) as the cube?
yeah yeah something like that
Ok it took me a moment but figured it out
Red = A, Green = B, Blue = C, White = Result
This works:```cs
Vector3 ProjectAndKeepY(Vector3 a, Vector3 b, Vector3 c)
{
var ac = c - a;
var ab = b - a;
var yAB = b.y - a.y;
var yAC = c.y - a.y;
// Percentage along Y
float t = yAC / yAB;
return Vector3.Lerp(a, b, t);
}```
You calculate the percentage that C lies between A and B, but only on the Y axis
Then you use that percentage to lerp between A and B
There's your result
To clarify - A & B are the line points and C is the position you want to snap to the line
Thanks you so much man....this base will help me a lot
What's the last thing that you selected?
Hey there! I'm trying to implement changing map in my game and I think unity is taking the piss at this point.
I have a bunch of objects on my map and what I want to do it first move the objects parent into a _toDestroy variable and rename it to "ToDestroy" And then reset the _objects to a new "Objects" Gameobject to get the new sets of objects:
private GameObject _objects;
private GameObject _toDestroy;
private Dictionary<string, GameObject> _objectsDict;
public void ResetObjects()
{
_objectsDict = new Dictionary<string, GameObject>();
if (_objects != null)
{
Debug.Log("Reset");
_toDestroy = _objects;
_toDestroy.name = "ToDestroy";
_toDestroy.SetActive(false);
}
_objects = new GameObject("Objects");
}
And then, after the map is generated, I send an event to clean up the old objects:
public void DestroyOldObjects(EventArgs args)
{
if (_toDestroy != null)
{
Debug.Log("Destroying old map");
Destroy(_toDestroy);
_toDestroy = null;
}
}
HOWEVER. Some dark magic happens here. The _toDestroy rename doesn't reflect AT ALL on the hierarchy, so does the change of active. BUT if I check using SceneManager.GetActiveScene().GetRootGameObjects() it appears and has the name.
Also the Destroy literally has no effect at all. All the objects are still on the game.
Everything is done async using CoRoutines and Events.
One thing to note is that some code is also removing the whole TileGrid and this time, the Destroy works. So the issue is really this particular GameObject....
Any idea? This is driving me crazy
are you sure it's being called on the object you expect, and not a prefab or something? try adding the object as a context param when you log the reset/destroy log messages and make sure it's highlighting the right one
Object is initialy create like: _objects = new GameObject("Objects");
It's used as an empty gameobject to contain all the dynamically added objects on the map.
It is not a prefab however all its children are technically instanciated prefabs. Could it explain that?
By context param, what do you mean? Just doing `Debug.Log("My object" + _toDestroy) ?
@strong night does it work when you have only 2 objects?
like create the first instance -> then call ResetObjects() -> delete old instance -> and see the new instance
That's what's meant to happen. But I do end up with 2 Objects at the end because the actions I do on the original objects have no effect
besides the issue ur facing could u describe your use case a bit? this feels like a very janky way to go about things
yea
So I'm making a 2d topdown game with random map generation and map to map travel. The idea is that when I move from 1 map to the other, I destroy everything and rebuild everything. So basically destroy the tileGrid and the objects on the map and load the new map
The tileGrid is successfuly destroyed but the objects on the map keep persisting
That was my initial approach, changing the coordinates on my world for my player and its approximate arrival coordinates on the map itself and reload the scene to consumer those, but it was super flaky, so I thought I'd try that way
And other than the objects persisting for some dodgy reason, everything else works so it sounded like a good idea lol
wym flaky
scenes is definitely how I'd personally go about this I think
kind of what they're designed for
but if you're adamant doing this way
how about using prefabs instead of moving over a bunch of objects from one parent to another?
So the objects themselves are original prefabs (the ones in the parent)
I'm not looking into moving them, I'm hot swapping maps. So map 1 has a bunch of trees scattered around the place and map 2 will have trees to be different numbers, coordinates etc...
So when moving from map 1 to map 2, the content of map 1 needs to be wiped and leave place for map 2
But the Trees are prefabs
I might give another go at the scene as it'll probably be more robust if I get it to work. I've been doing a lot of experimenting since I tried it, so maybe it'll make more sense now to me
well from that description it's like a perfect usecase to just readd the scene and unload the old one
you can use a scene like a prefab of ur entire map
and just have ur random placement logic happen whenever the scene is loaded
Hmm interesting. Yeah I'll give it another go
btw if that is the case and you end up doing this way I'd just destroy every tree then instantiate a bunch of new ones
no need to do this parent swapping voodoo
more trouble than its worth I think
Oh but that's what I'm trying to do
I destroy the parent with all of its content
And create a new one
IT just happens that Unity isn't doing the Destroy at all
The "swapping" from Objects to ToDestroy is just to allow creating new objects under a new parent while the Destroy happens as Destroy is a bit more async
ah sure thought it was something else from ur original description
but i doubt the issue is like... something wrong with destroy
probably some issue with the coroutines instead
Maybe... I'll try the scene way so hopefully it won't be a problem I have to deal with lol
I definitely don't think its worth the performance of using non main thread just to destroy a bunch of stuff; especially since it sounds like something that doesn't happen very often
scene loading and unloading is 'async' so you'll get the same kind of gameplay fluidity
Yeah, funnily enough, most of my code was very compatible with scene loading. It works out of the box lol! Thanks for the advices ๐
Hello, trying to make an attribute for hiding variables based on values of other variables. It works (kind of), but it completely resets indendation, so nested properties render all the way to the left. I don't modify EditorGUI.indentLevel at all, so no idea how this happens. Any tips?
EDIT: I tried printing EditorGUI.indentLevel, it's always zero. I don't know why or how.
Okay I was able to fix it by setting the indent level myself by counting the amount of periods in the property path. Still no clue why indentLevel was zero, isn't it meant to be handled automatically by default?
how can I adjust the crinkliness or seek sun of a tree from a script?
this is what the "tree" looks like, i'd like to dynamically change the crinkliness of the middle portion
if anybody knows much about this stuff - I am rendering from a camera to a RenderTexture, which has square dimensions (see screenshot). If the camera viewport is not square, does it just try to render the maximum square size centered on the middle of the camera viewport?
I'm pretty sure this is the case... what do I want is to have a visual indication, perhaps like a red square on the camera view that outlines the part that will get rendered to the RenderTexture.
if that's possible please let me know
something like this maybe?
or maybe that's stupid and I should output the render target to a different camera..
Hi, i need urgent help in building an apk for my game. please lmk if you can help <3
i have a script that simply changes one color property of a shader of a referenced material...I am using addressables to load and unload one scene where the object with that material is.... suppose scene 1 holds the object with the material and scene 0 holds the script to change shader value....Now:
scenerio 1 -> changer script in scene 0 and material is referenced in that scene...scene 1 is loaded on button pressed
scenerio 2 -> changer script in scene 1 and material is referenced in that scene...scene 1 is loaded on button pressed...
in scenerio 1, shader property doesn't change, script works but shader property doesn't change...
in case of scenerio 2, shader property changes
mainly, when i reference my material in the scene where the object is, script works fine...
but when material is referenced in another scene and then the scene with the object is loaded, shader properties doesn't change...
can anyone help please?
what type of help do you need?
Don't ask to ask, and use the correct channel for your question. This is a coding channel and from your message it seems like you'd want to use #๐ฑโmobile
When I press Build, I get a quick process popup and then it closes. When I go to the folder where I built it it's empty. I tried doing a clean build too
Without you sharing specific details and specific code, it's impossible to answer this question. The exact details of:
- Which mateirals you're referencing and how
- What code you're using to change the material properties
matter a lot
does it show successfully built type msg in console?
public Material mat;
public Color colorToSet;
public Color colorToSet_01;
public AssetReference sceneRef;
public AsyncOperationHandle<SceneInstance> handle;
void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
handle = sceneRef.LoadSceneAsync(LoadSceneMode.Additive);
}
if (Input.GetKeyDown(KeyCode.A))
{
mat.SetColor("_Value", colorToSet);
Debug.Log(mat.GetColor("_Value"));
}
if (Input.GetKeyDown(KeyCode.S))
{
mat.SetColor("_Value", colorToSet_01);
Debug.Log(mat.GetColor("_Value"));
}
}
material is referenced via dragging it to inspector
So what makes you think this is or is not working in any given scenario?
in build...sry not to mention this
That channel was tucked away, I missed it, thanks @robust dome
you are welcome friend
I think I know what's going on here
If you have a direct reference to an asset and you also load it via Addressables, you'll wind up with two different assets in the built game
This will not happen in the editor.
maybe that's why it is happening...can you tell me any way to fix that?
I ran into this problem while working on my game's settings system. Each setting is a ScriptableObject asset. I was using Addressables to easily load all of them when the game started
Everything broke because the Addressable version of the assets were unrelated to the non-Addressable version
Your second case works because the reference to the material is from an Addressable scene.
I think you can make the first case work if you replace the direct asset reference with one that goes through Addressables
man, that hurts a lot
In my case, I just stopped using Addressables -- it was basically equivalent to putting everything in a Resources folder
I was not actually using any of the system's features beyond "give me all assets!"
so instead of referencing the Material directly, store an AssetReference
(I'm kind of murky on this, so maybe ask in #๐ฆโaddressables if that doesn't fix it)
Now you'll get the asset that the Addressables system knows about (which is the same asset that you'd get if you referenced the material from an Addressable scene)
As I understand it, a common pattern is to have a single non-Addressable scene whose sole job is to load up an Addressable scene
thats right
one thing, how can I access the material properties when referencing that material to assetReference?
does someone know if its possible to do android/pc communication over usb?
You'd need to load the asset through the Addressables system. At that point, it's business as usual.
This does not happen in the editor because Addressables just fetches the asset straight from the AssetDatabase, by the way
hey i'm a level designer working on a project.... and there is something I don't understand. Dev is insisting on loading entire levels as prefabs instead of using scenes... is there... any good reason to do this? It seems like it breaks all kinds of dependancies and introduces merge issues when people update sub-components of the prefabs. But I don't know enough about code to form a counter argument, and none of them want to explain to me why they want to do it this way.
Well, you'll have identical issues with scenes!
Nested prefabs should help you avoid such conflicts, though. Suppose I have this for an enemy:
- Enemy (Prefab)
- Body
- Weapon (Prefab)
I can change the Weapon prefab while someone else is messing with the enemy's Body object
yeah but I mean..... the entire level is a prefab... probe data and lightmaps dont work... though we haven't decided on using that.
oh yeah, that's going to be uh
๐ฅ
I've never really looked into trying to put "scene data" into prefabs like that
Cross-scene references are a bit annoying to handle, so instantiating a giant "level prefab" could be mildly more convenient
normally, you have to wait for the scene to activate, then try to find the objects you need in it
why is my scale messed up after i call this function
public static void SetParentT(this Transform target, Transform parent)
{
var targetScale = target.localScale;
target.parent = parent;
target.localScale = targetScale;
}```
because if i just drag it the editor as the child it works (last image)
my barely educated guess is to allow the UI to live in a single instance and not have to hand data back and forth constantly
cause aparently thats a common frustration
but i really don't know :/
I just punt my game's UI into DontDestroyOnLoad and leave it there forever
I saw that in favor of prefabs, and memory issues as an argument against level prefabs, but the source is like... no data reddit posts
In another game, I additively load a "UI scene" at game start and then never unload it
That's roughly equivalent
When you switch parents, your local position, rotation, and scale will change so that the world position/rotation/scale are preserved
You're setting your local scale back to its original value
If your old parent's scale was [1,1,1] and your new parent's scale is [2,2,2], your local scale will get halved
If you then reset your local scale to its original value, your apparent size will double
the object didnt have a parent, and the new parent's scale is 1,1,1,
The new parent's local scale is [1,1,1]
But perhaps it has a parent of its own!
The values you see in the inspector are the local position/rotation/scale
Android does not have a USB port, how exactly do you plan to establish communication this way? What problem would this kind of communication help you solve?
My script is enabled but does not work and idk why it gave me the DEBUG called LightTool script started!
Hastebin is a free web-based pastebin service for storing and sharing text and code snippets with anyone. Get started now.
what its supposed to do? and whats happening instead
What are you expecting it to do and what is it doing instead?
๐ฎ
Jinx
Its supposed to light the firework if i press mousebutton 0 and does nothing
Well first off it seems to expect you to click on something
Yes and it has a collide and the right script
also i would say Debug what you hit. before hitting any if statements
So what gets logged when you click on it?
I did that also
Nothing
Then the code isn't running at all
Yea i know but script is enabled
Debug.Log("Mouse click detected!"); is not working ?
you have to find out where its "failing" in your function, if its running at all
It should at least say mouse click detected
nope only debugs the start function
yea i know thats why i am very confused
Are you clicking in the game view? Or in scene view
likely this is getting disabled or gameobject is at some point
Game view i am not that stupid
Also make sure the game isn't getting paused
Yea i am also doing that
Hey you never know we see everything here
Like, for example if you have Error Pause on
I dont have that because i dont get an error
Yea i have 1 year experience but have not made games for like 4-6 months so i wanted to start again
is this gameobject or parent being set to not active ?
What do you mean by that?
oh btw this doesn't work on unity objects Camera.main? the ?
you know what a disabled gameobject is?
still it did not work before
yea its enabled
specifically, it will only check if the reference is genuinely null -- it doesn't care if the object will compare equal to null (e.g. it's a destroyed unity object)
Log something in the Update method. I want to see if it is running at all.
ok. this is where the script is?
are you actually clicking in your game view twice to make sure you're like inside the game view?
Yes it is and yea i click in gameview like 10 times
Ye
Wait update does not work in that script
No debug
Did you save your code in your editor?
And did Unity recompile
I press save every line i write
Did Unity recompile? Do you have auto refresh off?
It recompiled
type some garbage into your code editor and save it. does unity produce an error?
if so, then it is, indeed, seeing your new code
Script works fine just not update
have you tried removing the garbage on the line above Update?
That means that this behaviour is getting disabled (or its object is getting deactivated).
This was intentional
ah my bad
I wanted to make sure Unity was actually seeing the changes
Its on my player and i have a toolwheel script that activates the tool as its selected
You can check by logging something in OnEnable or OnDisable
let me try
When i select it
it Enables and disables QUICKLY
What do you mean Android does not have a USB port? I mean the type-c port thats on my phone. i want to have a server from the phone to the pc over USB.
well there's your problem
yea but now idk how to fix it
You must have an error in your tool-selection code
yea ik
It certainly is
That's what USB is for
Communication
Does converting ASCII fbx resources to Binary can save space? Or Unity already converts them at build time?
Unity converts everything into its own internal formats as part of the import process
The file format is irrelevant
This talks about how that whole system works. Neat read.
I guess the question here is "how do I do that from within Unity?"
That sounds scary
Ok, I thought you choose the type of format you compress into, like in bitmaps, but I guess it use it's own propriety format?
I dunno how models work
How do I remove Unity's own logging like:
No texture data is available to upload.
...from the console window in a server build?
i think somewhere in project settings
Use Player Log Enable this option to write a log file with debugging information. This option is enabled by default.
https://docs.unity3d.com/Manual/playersettings-windows.html
I wouldn't. I would do it in native android and use android interop stuff @finite olive.
Android USB documentation starts here https://developer.android.com/develop/connectivity/usb
I'll have a look at that, thanks!
That didn't seem to work, the log messages still appear in the log window
oh maybe its some warning to disable? . would need to look into it more
The log file might have a stacktrace to look at
Could help you figure out why that's getting logged, at least
The log file does not have anything extra, I want to remove these:
Ah, all of that stuff that falls out during startup?
I wonder if you can make the console window clear itself
I don't know of a way to suppress those logs, though.
And that's because I cannot change the formatting of those log messages to have a timestamp or anything
maybe something to do with command line arguments and some option to turn verbose
https://docs.unity3d.com/Manual/PlayerCommandLineArguments.html
check here if you can, I'm on the go and can't atm
I tried to get instrumentation-based profiling to work with Superluminal, but after adding the Superluminal DLL and calling SuperluminalPerf.BeginEvent("foo") and .EndEvent(), they don't show up regardless
It does work when adding the superluminal DLL in a separate C# project (through nuget) whose DLL was included in unity, but this is not that useful
Did anyone get that to work?
There is one called -nolog but that didn't work
I am on a project where I need to log player position, head rotation, etc. most importantly I need to log collisions. I only want to log a collision on first contact. (Basically onColliderEnter) the issue is that our player uses a character controller and from my understanding that doesnโt pair well with a rigid body.
Will I have to maintain a hash of all the collisions?
Or is there a much better/cleaner approach
Character Controller has it's own collision event
what are you thinkig of "hashing" here, exactly?
I'm confused by "maintain a hash of all the collisions"
There could be multiple collisions at the same time, so every time charactercontrollerhit is called, it will attempt to add the object (or characteristic of it) to a hashset. If the item is already in the hash it it gets ignored, else log it. Then using โoncontrollerexitโ, remove from hash
I would recommend using this: https://assetstore.unity.com/packages/tools/physics/kinematic-character-controller-99131
Internally it keeps track of a thing called KinematicCharacterMotorState which I believe already has all the things you want.
so one important thing to note here...
a character controller is not going to produce the normal collision events when it tries to move into a solid object
it even exposes a handy GetState() function to grab the state whenever you want.
It never actually overlaps with the obstacles. That's the entire point -- it figures out a new position that's not inside of a collider
you would just need to implement Equals() and Hashcode() for the KinematicCharacterMotorState struct for it to work properly with HashSet as you desire. Your IDE can likely generate these for you automatically.
Gotcha, I was planning on storing their names if I go that route, but thanks for the tip!
If you need to keep track of which things you've hit, you'd want to keep track of a collection of Colliders
I'm iterating upon a state machine, where each state subclasses CharacterState, and a CharacterStateFactory tracks all possible character states so that, when checking if a state should be updated, a given CharacterState checks some conditions and, if applicable, returns the relevant state from CharacterStateFactory . I'm doing a lot of prototyping right now, and so I'm finding it very tedious to:
- define a character class
- tell the factory about the new class
Is there any pattern that I can use to have the factory implicitly know about all of theCharacterStateclasses I create?
As I'm writing this out, I'm considering to just replace my Factory with aDictionarymanaged by the Character. Upon checking for a new state, I can see if theDictionaryalready contains an instance of the specifiedCharacterState, and if not, I can instantiate an object of the specified type and add it to the dictionary. I guess the problem with this implementation is that I can't preinitialize the states because I don't know what all of the applicable ones are, which is why it would be nice to know all of the classes beforehand.
can you share the factory code?
If I'm kicking off an animation with SetTrigger(string id) .. is there an easy way to yield in a coroutine until that state is complete? Or is there maybe an easier way to embed an animation in a coroutine?
you could use a StateMachineBehaviour here
that lets you run code in response to a state entering or exiting
it's a little awkward because this is on the animator controller asset, so it can't reference objects in your prefab or in the scene
I've used this code a while ago, you can probably adjust it slightly if you need use a trigger instead of state name or evaluate the duration of a different layer
public static IEnumerator PlayAndAndWait (this Animator animator, string stateName)
{
animator.Play(stateName);
yield return null;
yield return new WaitForSeconds(animator.GetClipDuration(
yield return null;
}
public static float GetClipDuration (this Animator animator, int layerIndex)
{
AnimatorClipInfo[] currentClipInfo = animator.GetCurrentAnimatorClipInfo(layerIndex);
if (currentClipInfo.Length == 0)
{
Debug.LogError($"Animator is not playing! {animator.gameObject.name}");
return 0;
}
AnimationClip currentClip = currentClipInfo[0].clip;
return currentClip.length;
}
I could do something janky like while (animator.state != "myTriggerAnimationName") but seems bad?
that also works
hm, that's .. better, perhaps
Just skimming the docs of Animator, I'm surprised there isn't a play animation (as a coroutine)
it's probably better because you're avoiding the WaitForSeconds allocation, depending on the frequency that it's going to be called
but unfortunately the animator API sucks
I don't care about that :p
can you only get the clip info if it's currently playing? I'm also worried if the animation doesn't start on the same frame as I set the trigger - I don't know when animations start when you set trigger
(in update)
you could use this to set a field back to false upon exiting a state
I wanna KISS - I pretty much just wanna be able to do something like:
public IEnumerator InteractCoroutine(Vector3 target, Action interactDoneCallback)
{
EntityMesh.transform.LookAt(target);
EntityAnimator.SetTrigger("Interact");
yield return null; // pause until animation is done here
interactDoneCallback?.Invoke();
}
ideally something that's one line on that yield would be great
I've added a yield return null before actually waiting for the clip duration there
it's pretty old code, but I think it was necessary for the animation to properly start
oh, to ensure the trigger is consumed and the clip[0] is the correct clip?
most likely yes
i presume it has to wait until the animation update (which occurs after the Update loop)
just saw that the code is not even compiling ๐ sorry about that
yeah - i'd have to dig through the docs but i imagine setting the trigger in update might not put the animation into that state immediately - maybe next frame, maybe later in the frame's lifecycle, etc
shouldn't be too hard to fix
use a StateMachineBehaviour. it does exactly what you want here -- although you will have to set one up for each animation state you're interested in the entering and exiting of
I'd have to fuss around to make an example because I don't use Mecanim very much in actual game dev -- just for VRChat nonsense ๐
i still have to tie the animations to those states manually, right?
I also don't know exactly how clips blend and how that'd affect it all.. like during a clip blend, which animation is considered playing (probably the "before" animation? guessing before looking)
This would not have anything to do with the actual animation clips -- or, more generally, motions
Yeah, I'm reading it.. I don't see how I'd tie an FSM to the animator easily though?
Like.. if I'm understanding this right, I'm going to need to listen to what clip is currently playing in Update, and if it's different than the FSM thinks, change the state? (and subscribe externally to whatever I need - OnStateExit probably?)
You would add a StateMachineBehaviour to whatever states are entered when you set the "Interact" trigger. They'd raise an event in OnStateExit.
public class NotifyOnExit : StateMachineBehaviour {
[SerializeField] private string label;
public event System.Action<string> OnExit;
override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
OnExit?.Invoke(label);
}
}
A lot like animation events, but it's dealing with an animation state, rather than a specific animation clip.
You could subscribe to all of these pretty easily:
foreach (var notify in animator.GetBehaviours<NotifyOnExit>()) {
notify.OnExit += HandleExit;
}
where HandleExit takes a string and decides what to do based on that
public IEnumerator InteractCoroutine(Vector3 target, Action interactDoneCallback)
{
EntityMesh.transform.LookAt(target);
EntityAnimator.SetTrigger("Interact");
yield return null;
AnimatorClipInfo[] _clipInfo = EntityAnimator.GetCurrentAnimatorClipInfo(0);
float currentLength = _clipInfo[0].clip.length;
yield return new WaitForSeconds(currentLength);
interactDoneCallback?.Invoke();
}
this is where I'm at now.. seems fine?
So, if you configured your interaction animations to all send a message named "Interact Over", you could respond to that
I'm not sure I need all the FSM stuff since I compose my animations through coroutines currently
(ie, I don't need to create "starts" and subscribes to "ends")
this would misbehave if the animation state got exited early or if the speed of the animation state was anything other than the default. it also only works if the state is on the base layer
if something prevents the animation state from ever entering, this will erroneously decide that the interaction completed properly anyway, too
(after a time period that depends on what state you happen to be in)
Yeah, understood
So it'll mostly work
This works pretty well as a quick and dirty solution for me - the story beat here is hard coded so there's nothing else going on in the game
the "interact" animation is that mouse doing the hand plant and looking around.. then i return control to the camera which unzooms
The state machine behavior callbacks give you a reference to the Animator component in the scene
hm.. i have a reference to the renderers (and animators attached to them) in another way, but .. I don't know if I like how my objects are composed currently
this is coming out nice 
thanks.. lots to do still (as always)
the end result of stuffing the clip "wait" in the renderer coroutine is that I can compose this shot with code like this:
private IEnumerator Story1BBeatCoroutine(Action callback)
{
// Save zoom clicks
_zoomClicksDuringSpecialAnimation = _currentZoomClicks;
// Track target
OnTrackTargetRequested(InterfaceManager.CommanderRenderer.gameObject);
// Zoom
_currentZoomClicks = 0f;
yield return new WaitForSeconds(CameraZoomTime);
// Small pause before animation
yield return new WaitForSeconds(0.25f);
yield return InterfaceManager.CommanderRenderer.InteractCoroutine(InterfaceManager.LookAtCameraVector, null);
// Zoom out
_currentZoomClicks = _zoomClicksDuringSpecialAnimation;
yield return new WaitForSeconds(CameraZoomTime);
callback?.Invoke();
}
instead of setting a callback on the renderer's state change back to idle (then continuing)
I don't like how that kind of code (embedded lambdas) looks.. just a personal preference
blahblahblah.OnStateExit = () => {
blahblahblah.DoMoreStuff();
};
or whatever the syntax is.. I just sorta hate it :p
Feels like something the animator timeline would be good for, no?
You can also provide a named function if you want
Of course, this could also just be a place to use animation events
yeah, I dabbled a little bit with timeline but .. it didn't play nicely with cinemachine for what I'm doing
I really have the camera movement/ui dialed in how I want it.. I did some timeline prototypes but it didn't feel great
I might still come back to it for some shots that need more .. uh.. moving parts. Doing it in code isn't great, but it's good enough for now, and allows me to maybe embed "story beat" camera shots and pauses into configuration content
Does anyone know why my look sensitivity increases with lower frames rates. I used Deltatime but that didn't seem to fix it at least not when I'm using a mouse. on a controller it works as you would expect.
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerLook : MonoBehaviour
{
[SerializeField] private InputActionReference look = null;
private Vector2 lookInputValue;
[SerializeField] private float mouseSensitivity = 25f;
[SerializeField] private float controllerSensitivity = 200f;
private float xRotation;
private Transform playerBody;
private void Awake()
{
playerBody = this.transform.parent;
Cursor.lockState = CursorLockMode.Locked;
}
private void Update()
{
lookInputValue = look.action.ReadValue<Vector2>();
float sensitivity;
if (ActiveDeviceManager.instance.activeDevice == ActiveDeviceManager.ActiveDevice.MouseKeyboard)
sensitivity = mouseSensitivity;
else
sensitivity = controllerSensitivity;
float lookX = lookInputValue.x * sensitivity * Time.deltaTime;
float lookY = lookInputValue.y * sensitivity * Time.deltaTime;
xRotation -= lookY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
this.transform.localRotation = Quaternion.Euler(xRotation, 0, 0) ;
playerBody.Rotate(Vector3.up * lookX);
}
}
Don't scale mouse input by Time.deltaTime. Learn why...
what the hell is this sorcery
File access error. That's what you get for putting your projects in sensitive directories, like users.
Move it to the disk root or somewhere near it and try again.
been working like that my whole life, I think its because I had to restart my pc b4 and the project was booting up
but lemme try
never fucking mind, somehow it was a command line argument specifying port and ip ๐
it worked an hour ago tho
thanks anyways ๐
no clue how that worked
That... makes a lot of sense lol, thank you.
Only thing is not my mouseSensitivity is at like 0.1 and my controllerSensitivity still at 200 for similar feel on both but that's not really an issue lol
hey guys im having so much trouble trying to setup a project for Unity ML
Also !ask
:thinking: Asking Questions
:mag: Search the internet for your question!
:book: Use the API Scripting Reference and User Manual and this troubleshooting site for commonly posted issues.
:wrench: Attempt to debug your issue.
:thought_balloon: Find an appropriate channel by reading the name and description in #๐โfind-a-channel
:grey_question: And don't ask to ask, ask a full question illustrating with screenshots if needed.
-# For more posting guidelines, go to #854851968446365696
the channel is basically dead thought i would get better odds of someone helping out here ๐ญ
you'd have better odds of someone helping if you post your question in the correct channel and with some actual details
my bad boss
is there a way to debug code that fails 1/5 times testing the same thing? fsr Im saving data to a file: a string, vector3, and another string using JSON. It saves just fine, so far ive been able to save the file successfully 100%, and debug it to know the transform is being applied. yet the objects still get instantiated at 0,0,0 some times. Also, im not sure if it also deals with the weird place issue. ill post a vid and code
nvmd i cant even send a 20 second vid in 480
Adding more debugs and trying to reproduce the issue. Then looking through the logs to see where it went wrong.
Conditional breakpoints are also an option.
Are you using Rigidbodies with interpolation enabled?
the debug you see there is the actual game object data, not the serialized class data, so i dont know wtf is happenin
yes
that shouldnt reset the objects location tho right?
Set Rigidbody.position, not just the transform's position
thats a thing?
When you have interpolation enabled, the Rigidbody will set the transform position every frame
This will cause it to lose whatever position you assigned
You need to directly tell the rigidbody where it needs to be
that could be whats causing the other handling issue
(you could also set the transform's position as well, so that it's immediately in the right spot)
is that in the fixedupdate method?
You'd want to do this during instantiation
i see
You may need to use GetComponent to fetch the rigidbody (or add a reference to it on whatever component type you're referencing the prefab as)
public class MyPrefab : MonoBehaviour {
public int whatever;
public Rigidbody rb;
}
I very rarely reference prefabs as GameObject!
Technically, setting transform position, should invalidate rb interpolation imho. But the thinking is correct: there are many systems that might try to move your object if you go against them.
saving and loading is real tricky, i got it setup for the most part, just these weird quirks
ill try it and report back
It works fine if interpolation is disabled
Alternatively, you can call Physics.SyncTransforms() after instantiation. This is necessary if the collider needs to be in the correct location immediately
I've seen problems in the past where people instantiate and position objects, then immediately try to do a physics query
Ah, physics queries would definitely lie in that case, yes.
The physics system does immediately know about the new collider and rigidbody, but if you then set the transform's position afterwards, it won't notice that change until the next physics update
so rb.position =
transform.position =
then Physics.Sync
The last bit is only needed if you want the collider to be correct immediately
wouldnt hurt right?
If it can wait, I'd just set the two positions
okay
It'll be a slight performance hit, nominally
It could be a problem if you spawn tons of objects
You do want both of these so that:
- The rigidbody is in the right spot
- The transform isn't in the wrong spot for one frame
I don't know exactly when the rigidbody winds up updating the transform's position, hence the second point
i might have done better factoring than i thought ๐ฎ i only had to add one line lol
lets see if it works
idk if spamming a load script has anything to do with this but there the culprit is down there
it did better this time tho i have to say
you can see its serialized data applied to the monobehavior, but the gameobjects transform gets reset somehow
another test to load, quit, load quit and it happened maybe the 3rd time again
What other components are there on the object?
the pot object is the unique one, all objects that will be saved and or picked up will have these pertaining to them.
ive tried removing the handle script completely, same issue. it also does the same 'blip' when placing items. it feels like a plague, ill try and catch it one sec
I'm not sure I understand the issue correctly. What exactly is happening in that video? And what(when/where) goes wtong
the test is me picking up and placing the object, repetitively to get it in length for a video, but randomly it seems like the place transform never gets applied, but the grab handle gets nulled and the player drops it. Debug log in the dropped script would tell me if its coded to drop on purpose
but both issues seem like randomly nulled out transformations or something, that or the raycast is getting fubar'ed somehow. it just seems like timing than a written problem
i think its fixed on both ends.
TryGetComponent(out Rb rb){
rb.position
not rb.transform.position lol
What happens if you call GC.Collect in Unity with the parameter compacting as true? Since I read Unity's GC does not compact
how to make all existing disabled gameobjects take in this script in editor mode ?
[ExecuteInEditMode]
class temp : MonoBehaviour
{
private void Awake()
{
languageChangeText script = GetComponent<languageChangeText>();
script.FontSize = new FontSizeDictionary()
{
{ LanguageDataScript.LanguageCodeRes.ENG, script.enFontSize },
{ LanguageDataScript.LanguageCodeRes.CHT, script.tcFontSize },
{ LanguageDataScript.LanguageCodeRes.CHS, script.scFontSize }
};
DestroyImmediate(this);
}
}```
i know disabled cannot take in this script because they are not active, but i dont want to make them active either
they should be disabled in prefab mode
you could just have it grab all those gameObjects
aight
uh if they're part of prefabs just modify the prefab
oh wait the instances have different settings don't they, nvm
in fact i just think of a new way for it
[ExecuteInEditMode]
class temp : MonoBehaviour
{
private void Awake()
{
class[] allValidObj = GetComponentsInChildren<class>(true);
foreach (languageChangeText element in allValidObj)
{
element.FontSize = new FontSizeDictionary()
{
{ enum.ENG, script.enFontSize },
{ enum.CHT, script.tcFontSize },
{ enum.CHS, script.scFontSize }
};
}
}
}```
the root of any prefabs will always be active anyway ๐ฉ
why not use GetComponentsInChildren<languageChangeText>(true)
what's with the class there
i just used it
oh they are languageChangeText, i shorten them because its too long lol
i dont want anyone feels painful lol
i mean, that's just dependant on your screen size and zoom and whether you have the member list open
i think showing the actual code would be better than... that invalid code
does anyone know of a way to "undo" StaticBatchingUtility.Combine
like i can imagine a script like, storing what the data was before combine on meshfilters and meshrenderers, and resetting that
just wondering if anyone's tried and/or know of such a script already existing someplace
my theory appears to work anyway, a little bit hard to know if i've overlooked something but it does look correct
all i had to do was cache what mesh a meshfilter had originally, and reset that when I wanted to "uncombine" something
hi guys, i tried opening this project in unity 2021.3.6f1, it keeps giving me an error as shown. how do i fix this ? retry just gives the same thing, continue opens the editor but the whole map is pink and there are multiple errors
just launch it and then fix the HDRP version'
unity 2021.3.6f1
This is probably your main issue
You need to update Unity to the latest version of Unity 2021.3
That would be 2021.3.46f1
okay ig ill just delete my current version and update to latest
what is the latest version
sorry havent done unity in years now
Read my message
Anyway it'll show up in the hub
if I have two colliders on a single object and I am trying to watch for when the player enters the only total combined collider shape(in this case like a T shape), what's the best way to handle this?
Right now I have it store the game object when OnTriggerEnter() is called and forget it when OnTriggerExit() occurs, but it still triggers sometimes when walking through the points where the two box colliders overlap
if they're for the same thing, why not use a single polygoncollider?
Consider counting how many colliders you're overlapping
Add one when you enter, subtract one when you leave
These are 3D colliders
You could use a mesh collider, I suppose, but you'd need to make a mesh!
Yeah, sorry I should have mentioned they are not 2d
You could also use OnTriggerStay -- set a flag to false in FixedUpdate, then set it to true if anything is overlapping
This may work so I'll try that. I've considered the mesh collider but yeah I'd have to make a mesh which isn't ideal
Thanks. gameObject worked.
Is there a way to initialize the states in the state machine once with the owning gameObject and the components that the state will use?
This doesn't work:
public override void OnStateMachineEnter(Animator Animator, int StateMachinePathHash) {
base.OnStateMachineEnter(Animator, StateMachinePathHash);
GameObject = Animator.gameObject;
if (!GameObject)
Debug.Log("Game Object is null!");
CharacterComponent = GameObject.GetComponent<CharacterComponent>();
this.RigidBody2D = GameObject.GetComponent<Rigidbody2D>();
this.Animator = Animator;
}
Animator.gameObject is null when it enters the state machine.
public override void OnStateUpdate(Animator Animator, AnimatorStateInfo StateInfo, int LayerIndex) {
CharacterComponent = Animator.gameObject.GetComponent<CharacterComponent>();
}
This works and it will do for now, but this looks like it doesn't have good performance. I think I'll be able to move this to the OnStateEnter:
// OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
public override void OnStateEnter(Animator Animator, AnimatorStateInfo StateInfo, int LayerIndex) {
CharacterComponent = Animator.gameObject.GetComponent<CharacterComponent>();
}
Which is better, but I'll still need to initialize the variables on each state enter, which is still not great for performance.
@hexed pecan can you please help if you don't mind the ping
I thought, animator's gameObject wouldn't be null when OnStateMachineEnter is called.
How do I initialize all the variables once when state machine enters?
hi i have public array string, i want to pass arabic texts but when i pass string it like seperate each words and like make ewwish and not understandable. how to fix that
I do not understand what the problem is. You'll need to show an example.
you need rtl dawood
in tmp it is an option you can enable but i don know about the inspector fields
It looks like Unity 6 finally has proper RTL text support in UI Toolkit (which is the system used for the inspector, by default)
but it has to be turned on by the creator of the UI; I don't know if the inspector does that
It looks wrong when I paste that example into the inspector in my Unity 6 project. Darn.
What do these errors mean?
Network error at a guess
A bit of googling says it's ... something messed up with unity, cause unknown. Potentially related to cache/appdata log file size, but mine seem reasonable (a few GB). I also have the cache on a windows drive pool, so maybe something is broken under the hood there
It seems to have gone away though. ๐คทโโ๏ธ
I have a series of entities in my game that inherit from an abstract gameobject. I'd like to staple some particle effects to all the prefab entities. There's no prefab associated with the abstract GO, unfortunately. Is there a way to do this without linking each and every prefab?
IE:
public abstract class EntityRenderer : MonoBehaviour
{
// stuff like:
[SerializeField] private ParticleSystem CastHealParticleSystemPrefab; // x 20
}
public class ScoutRenderer : EntityRenderer { } // x 20
There's a ScoutRenderer prefab, but I have to link the scout to the heal prefab. If I have to link these all one by one, it's gonna be a pain in the butt.
OnValidate ?
There is also reset
Worth the time in making some prefab variants if you're going to be editing the base
anyone have any issues with accessing the camera on an ios device? Attempting to access the camera and display is via a webtexture but just getting a black screen.
The first thing that comes to mind is a permission issue
Hi everyone!
I'm working on a 2D game with endless enemy hordes, currently capped at 200 enemies on-screen, but I plan to increase it or even remove the limit for an endless mode. I'm implementing health bars for enemies and considering using world-space canvases.
However, I'm concerned about potential performance issues with so many health bars. Are there any better alternatives to using world-space canvases to handle enemy health bars efficiently? Any ideas or suggestions would be really helpful!
For huge numbers of enemies, I'd consider writing a little shader that renders a healthbar on a single quad
I did that for these meters -- not for performance's sake, but because it made it easier to get the exact look I wanted
(shh, i didn't steal these from Splinter Cell)
these are rendering with a normal Image in a Canvas, mind you
Before you do anything, though, profile it (:
compare a few things:
- Many canvases with one bar each
- One canvas with all the bars
Each canvas is a drawcall so those tutorials are a meme
Most performant way is doing it single material shader using UVs to control the quad's texture gradient
or by doing it through vertex colors if you don't want to use a gradient
Any time a canvas is dirtied - ie, anything on the canvas changes - the entire canvas has to be rebuilt. Normally the advice is "don't be concerned about performance optimization prematurely" but if you're using health bars and have any sort of layout managers to render them, then you're gonna be rebuilding your canvas every single frame, and this will probably be pretty expensive - enough to notice an FPS drop with very little going on.
Make each enemy have it's own canvas, so you don't have to rebuild all canvases each time anyone's health changes. Instead, the canvases for each enemy can happily redraw and not be rebuilt unless they need to.
As far as world space canvases (versus screen canvases) - it's fine. You're better off using the world space canvases so you don't have to do tricky math to convert world space coordinates to screen space coords - but be aware of z-order/ layer drawing. You'll want to ensure your canvases are in a separate (higher) layer than your game so that enemies don't cover up other enemies health bars - unless that's what you want.
good point on using one big canvas
Yeah that's the way, but I'm not too sure about those instancing calls for URP. I think those options are usually provided within the material itself
No wait that's correct if you're not changing the mesh data itself
Will calling GetComponent get me the components on the gameObject?
Or on the Animator component itself?
https://docs.unity3d.com/ScriptReference/Component.GetComponent.html
Gets a reference to a component of type T on the same GameObject as the component specified.
I see.
Thanks, I'll just use GetComponent on the Animator.
