#archived-code-general
1 messages ยท Page 308 of 1
Whenever I start dragging something with this code, it seems to call the coroutine twice, am I missing something obvious?
private void Update() {
// Make sure the user pressed the mouse down
if (!Input.GetMouseButtonDown(0)) {
return;
}
var mainCamera = FindCamera();
// We need to actually hit an object
RaycastHit hit;
if (!Physics.Raycast(mainCamera.ScreenPointToRay(Input.mousePosition).origin,
mainCamera.ScreenPointToRay(Input.mousePosition).direction,
out hit,
100,
LayerUtility.GetLayerMask(Layer.UPGRADE)
)) {
return;
}
// We need to hit a rigidbody that is not kinematic
if (!hit.rigidbody || hit.rigidbody.isKinematic) {
return;
}
if (!m_SpringJoint) {
var go = new GameObject("Rigidbody dragger");
Rigidbody body = go.AddComponent<Rigidbody>();
m_SpringJoint = go.AddComponent<SpringJoint>();
body.isKinematic = true;
}
m_SpringJoint.transform.position = hit.point;
m_SpringJoint.anchor = Vector3.zero;
m_SpringJoint.spring = k_Spring;
m_SpringJoint.damper = k_Damper;
m_SpringJoint.maxDistance = k_Distance;
m_SpringJoint.connectedBody = hit.rigidbody;
StartCoroutine(nameof(DragObject), hit.distance);
}
how can you tell it's calling it twice?
from logs... but now it got weirder
I tried reverting to the old code
but my Debug.Logs that are in the other script are still being called
created another script to make sure and same thing, in inspector i can see it's the right one there
ima restart pc at this point something's off
ok i'm just dumb i think ifigured it out
Hello all, I have a code where I have a sprite with paint on it and I want this code to fade the paint away, I'm not getting any errors but it's actually making the alpha less faded and I don't know why
Pastebin.pl is a website where you can store code/text online for a set period of time and share to anybody on earth
that is one of the worst sites you could have chosen to share code with. there's no syntax highlighting and it is replacing characters with the html names
but what is the value of fadeAmount
any of the sites that the bot recommends for posting !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.
when i debug the value of the alpha it always says 255
Color uses values from 0 to 1 not from 0 to 255
when I debug it it says 255
Color takes values between 0 and 1
then why does it say it's 255
no idea Color32 is probably what you should be using
is currentColors perhaps an array of Color32?
and when I made fade amount 0.01f it still says 255 and doesn't work
yes it is
Color32[]
I'll put the whole thing in a proper paste site
that's why. but colorChange is Color not Color32 so that uses values from 0 to 1
well that likely won't fix the issue
is that not what we already said?
but at least that would make your math more correct
I put the code in a different page and added the relevant variables
when I change it to 32 it errors the alpha subtraction saying 'cannot convert float to byte'
I just realized Color at the beginning also needs to be Color32
doesn't change the error though
yes well you cannot subtract a float from a byte and expect to result in a byte
not quite sure why you don't just do
Color32 colorChange = currentColors[array_pos];
colorChange.a -= (byte)fadeAmount;
so that works now, thanks! It still lags whenever it runs the code, because it's checking all 10000 pixels of multiple sprites, not sure how to make it more cpu efficient, I may drop the fading altogether
I have multiple 100 x 100 pixel sprites that I paint on, I wanted the whole game to be paintable, and I wanted rain to wash the paint off, hence the fading code, but it lags the game when it does the fade, so i may not use it at all
Drop the code into a coroutine and wash one line of pixels per frame
also, the problem now, is the alpha cycles now, it fades, then when it becomes less than 0, it goes back to 255
My code says if it fades enough, to make it zero, but i'm guessing it's never 0 because it cycles back and that else statement never happens
well 255 divided by 50 will never give you 0
right
51 will
I assumed it worked like a float where if it goes less than 0 it will make it 0
nice
never assume
underflow
btw i dont know why you check the coordinate but you bound the loop at the same time
I'm not sure what you mean
the most obvious improvement you could make is that you're copying the whole pixel array out of the texture every call to ColorFade by calling GetPixels32(), if nothing else is modfiying the texture i think you only need to do this once?
so I could just GetPixels32() in Start and it would be the same?
that makes sense
I've already stored it in the array
and when I want to change it I can just SetPixels32() when I want to apply the changes
currentColors is already what I want it to be
you could also modify the texture data directly by getting the pointer with https://docs.unity3d.com/ScriptReference/Texture2D.GetRawTextureData.html, but you have to be a bit more careful
doing it that way would save the cost of copying every pixel back into the texture too
for (int x = 0; x <= 99; ++x){
for (int y = 0; y <= 99; ++y){
// Need to transform x and y coordinates to flat coordinates of array
int array_pos = y * (int)paintableSprite.rect.width + x;
// Check if this is a valid position
if (array_pos >= currentColors.Length || array_pos < 0)
return;
i don't know how much difference this actually makes but if you iterate over y then over x, rather than this way, the array indices you're accessing are sequential which i think is more more cache friendly? one of those tips i learned a long time ago and don't fully remember the explanation for lol
I just updated the paste
actually the code will wrong if paintableSprite.rect.width is not 100
every blank sprite I use is 100 wide
the range of x mismatch
I just changed the paste, it should be good now other than the return; I had, now that it's a coroutine what should I change that to
continue?
and I'm not sure how to do a row every frame like SteveSmith said
I think I did it right
is the width of every sprite you use are the same?
yes
every blank sprite I'm using this for are all the same dimensions
I have a folder of them in the assets folder they are painted on during the game and cleared when the game ends
64 blank 100 x 100 pixel sprites
the equivalent of return in a coroutine is yield break
thanks!
you have bound the loop and you dont need to check index out of bound actually, if you are really afraid of that then use debug.assert to verify if the dimension is correct
if you want to do that you can swap the two loops around so you iterate over y values first, then yield return null at the end of each iteration of the y loop
so you're saying
return;``` is unneccesary
yes
cool, thanks
I changed it to this
yield break;```
If alpha is already 0 I don't want it to check it
yield break is to stop the iterator
if you just want to skip that pixel you want continue , yield break exits the whole method
ok
so the place I have yield return null is making it wipe sideways
I need to put the x loop inside the y loop don't I
which is what simonp said
ok it does rows now, but I need to iterate it backwards
for(int fast=0;fast<arr.length;){
int bound=fast+column_length;
for(int slow=fast;slow<bound;++slow){
//access the element in flatten 1d array directly by arr[slow] to save one addition and multiplcation, assumn the array is picked as [columns in row0,columns in row1,...];
}//here you finished one row
fast=bound;
}
```a slightly faster way to loop, though i think you wont see any differences in terms of execution speed unless your image is really a long 1d array
to make it wipe from top to bottom
GetPixels32() does turn the pixels into one long 1d array
hey guys i ran into an issue, if i change my color through this script to black on runtime, it changes the color forever, even when you press stop the material color doesn't get reverted back. Does someone see the issue here?
yes, Material is a reference type. What you change in the dictionary will also affect the List and vice versa
materials are just regular assets so if you change them they stay changed, you could use a MaterialPropertyBlock to apply properties to the renderer instead which would avoid that
aight thx guys ill look into those things
Or access the materials from the renderers using .material this will create a copy
is there a Unity tool that shows what code is using the highest amount of processing power?
my cooling fan comes on when I play my game and I want to know where I can make code more efficient
learn to use profiler
How do I make code?
you write it
How do I write code
well, there is this thing called a keyboard with lots of buttons on it, in the right context you press the buttons in the correct sequence and, hey presto, you have code
๐
If you do not like the answers you are getting then perhaps you should think more carefully about the questions you are asking. Also this is not the channel for this discussion
Oh sorry
https://www.w3schools.com/cs/index.php
Pinned resources in #๐ปโcode-beginner
I think I got this painting thing down, thank you all so much for your help!
Does anybody know where A* puts its movement code? I'm trying to take the x,y,speed values to make my blend tree play the correct animations and rigid body values don't work, but when i use delta position, it also doesn't work
which a*
A* pathfinding
probably the package
doube click the file and open it?
how could I make a shader where the visible pixels follow a sinwave?
if(sin(unity_DeltaTime.w) != sin(i.uv.y)){
col.a = 0;
}
heres my latest attempt
what do you mean by the pixels following a sine wave?
Follow a sine wave how? Sine is just a function that takes an input and returns a value.
That could mean like 10 different things in my mind
effectively
square
but the only visible pixels are the ones on a sinwave
Maybe draw a picure of what you want it to look like
so you want an oscilloscope
probably
you want to only draw a pixel if it lies on the graph of Sin(x)
this is 2d, just to clarify
That makes it easier
so i'd do something like:
float expectedY = sin(uv.x);
float distanceFromExpected = abs(uv.y, expectedY);
float alpha = step(distance, something, threshold);```
i don't remember how the step function works
but basically this will say cut out the alpha for any pixel that's too far from the graoh
that step part definitely needs modification
one sec
ok so actually:
float expectedY = sin(uv.x);
float distanceFromExpected = abs(uv.y, expectedY); // how far are we from the true sine wave?
float alpha = step(lineThickness, distanceFromExpected);
col.a = alpha;```
should the thinkness be on scale of 0-1 or full ints?
it's distance in UV units
0-1
try this and see what you get I'm curious ๐
it makes sense in my head but obviously untested
this is also assuming alpha is 0-1 as well
oh sorry
Uhhh now that I think of it we might actually want:
float expectedY = (sin(uv.x) + 1) / 2;```
because sine gives us [-1, 1]
and we want [0-1] because UVs are 0-1
makes sense
and yeah if you want to change the frequency you'd do sin(uv.x * freq)
so:
float expectedY = (sin(uv.x * freq) + 1) / 2;
very very close
this is pretty cool in its own right
shaders are awesome
but i'd need to invert it so the transparent parts are red and the red parts are transparent
nice!
yeah try reversing the parameters in the step function
or getting rid of the 1 - part if you still have that
but yeah that looks great actually haha
huzzah!
nice!
rope arm!
I should probably make frequency and thickness adjustable from the editor
very neat. nice one @leaden ice
step is a hard cutoff, next thing i'd do is maybe try to explore a way to make it "softer"
but this is a great start
float alpha = 1 / pow(distanceFromExpected, 3); or something maybe?
just exploring things ๐
this is pretty good for now
got the vars changeable in the editor
shader code is so satisfying
really makes you feel like you have a lot of control over how you can make your game look
also feels like you are doing wizardry
now it actually looks like a grapple hook!
(didn't capture the whole screen which is why its cutoff)
Has anyone been able to send emails through Unity?
I was trying this code:
`
MailMessage mail = new MailMessage();
SmtpClient SmtpServer = new SmtpClient("smtp.gmail.com");
mail.From = new MailAddress("SENDER@gmail.com");
mail.To.Add("RECEIVER@gmail.com");
mail.Subject = "Feedback - " + SceneManager.GetActiveScene();
mail.Body = "mail with attachment";
SmtpServer.Port = 587;
SmtpServer.Credentials = new System.Net.NetworkCredential("SENDER", "SENDER_PASS");
SmtpServer.EnableSsl = true;
SmtpServer.Send(mail);`
Credentials replaced with placeholders. It looks like I'm receiving the following error:
Username and Password not accepted. For more information, go to 535 5.7.8 https://support.google.com/mail/?p=BadCredentials b7-20020a170902650700b001e245c5afbfsm11939832plk.155 - gsmtp System.Net.Mail.SmtpClient.CheckStatus (System.Net.Mail.SmtpClient+SmtpResponse status, System.Int32 i) (at <7a81e51e915a4e3a83ecbb5584005dd3>:0) System.Net.Mail.SmtpClient.Authenticate (System.String user, System.String password) (at <7a81e51e915a4e3a83ecbb5584005dd3>:0) System.Net.Mail.SmtpClient.Authenticate () (at <7a81e51e915a4e3a83ecbb5584005dd3>:0) System.Net.Mail.SmtpClient.SendCore (System.Net.Mail.MailMessage message) (at <7a81e51e915a4e3a83ecbb5584005dd3>:0)
Then I found this solution as a workaround:
https://gist.github.com/marcotmp/f6dc6cfcd2d6fb73978479d04bd7b0e5
But the issue is that when I went to google to set up App Passwords, I didn't see the option anymore. Is it no longer supported? I set up 2-factor authentication as well.
So with that being said, I was curious to know -- is anyone with a gmail account able to send emails out through Unity?
I'm currently in the process of getting a demo set up for beta-testing, hence why I was curious.
Thanks!
That's a really bad idea unless it happens to be a Unity instance running on a server
sending emails through Unity?
Unsure if this was meant for me haha
It's probably not the most secure if they get access to the source code, but it's just a way of me gathering feedback for now in a limited set of people with a demo build.
For context, I'm trying to build an in-game feature that allows the testers to give feedback as they play:
I would rather build that form in Google Forms and have the game open it in the browser
Unsure if there is a better way to go about it though -- this was the way I saw a few people going about it
If you include your Gmail credentials in the build, anyone who has it can dig them from there and then you're screwed
This is the first time I'm doing something like this -- but would my credentials be in the build?
I thought they would be hidden from public view
Google Forms sound like a good alternative though
For reference I'm the only one who has access to the repository I'm working off
How does the game send the emails if it doesn't have the credentials?
It's a burner account that I set up to send emails from -- those are the credentials that would be present in the code.
But I'm not sure how that would be seen in the build is what I'm wondering
A string is a string is a string, it would take me less than 30 seconds to pull your credentials out of your build
I'm not sure what the confusion is. The game must have the credentials to send the emails. So the credentials must be included in the build.
If the credentials are in the build, anyone who has the build also has the credentials
Might you know where these would be located?
I tried looking into the contents of the build that I created
I don't know what the file structure for Mac builds is
Ah no worries -- I'm thinking it might be safer for me to hold off on directly sending emails through Unity then from what I'm gathering -- maybe I can use the in-game survey to send responses to the Google Forms.
Haven't done that before so time to look into that haha.
Thanks for the heads up on that front!
It doesn't really matter where it is exactly, that's reverse engineering territory. What matters is that it's in there, and anyone malicious enough will find it and completely compromise that email account.
yeah no that makes sense -- even though it is a burner account, it's probably better for me to hold off haha
Thanks for the heads up!
I'll see if I can connect it to a public google forms instead
I have the below script attached to the Object (visible in the picture below) and when i click on the space bar i want it to call the Jump() Function via the Input Action
public class Player : MonoBehaviour
{
public float speed = 3f;
public float JumpForce = 11f;
bool Grounded = true;
Animator anim;
public SpriteRenderer sr;
Rigidbody2D rb;
Transform trans;
public InputAction playerControls;
Vector2 MoveDirection = Vector2.zero;
private void OnEnable(){
playerControls.Enable();
}
private void OnDisable(){
playerControls.Disable();
}
void Awake()
{
anim = GetComponent<Animator>();
sr = GetComponent<SpriteRenderer>();
rb = GetComponent<Rigidbody2D>();
trans = GetComponent<Transform>();
}
void Start()
{
}
void FixedUpdate(){
}
void Update()
{
Player_Jump();
Player_Movement();
Player_Animation();
}
void Player_Movement(){
MoveDirection = playerControls.ReadValue<Vector2>();
Vector3 dir = new Vector3(MoveDirection.x, 0, 0);
transform.position += dir * Time.deltaTime * speed;
}
void Player_Animation(){
float h = Input.GetAxisRaw("Horizontal");
if (h == -1){
anim.SetBool("Walk", true);
sr.flipX = true;
}
else if (h == 1){
anim.SetBool("Walk", true);
sr.flipX = false;
}
else if (h == 0){
anim.SetBool("Walk", false);
}
}
void Player_Jump(){
if (Input.GetButtonUp("Jump") && Grounded){
Grounded=false;
rb.AddForce(new Vector2(0,JumpForce), ForceMode2D.Impulse);
}
}
public void Jump(){
if(Grounded){
Grounded=false;
rb.AddForce(new Vector2(0,JumpForce), ForceMode2D.Impulse);
}
}
}
If you only need it temporarily, I think just using Application.OpenURL to a public Google Forms would be easier as suggested, you dont then need to setup any webhooks or anything to send to a form - if you need a more long term solution, maybe you can look into using a database, like MySQLite, to store the feedback, you can even store additional info like the point of the level the report was sent, or the time it was sent at, how many enemies were killed when it was sent, etc
Ah that makes sense, thank you! ๐
For now it's just trying to gather feedback from roughly 5-10ish people for a game build, so I'll stick with Google Forms for now, but I like the idea of a DB down the line if I end up with other stats :))
Thanks for the heads up!
Note that the above will have the same problem if you don't have your own backend sitting between (game -> backend -> database) and malicious attacker will just take your database credentials and compromise it.
yeah I was thinking having a middle layer might be important for that too
but makes sense, thanks!
For now I'll just see if I can collect feedback with a google forms ๐
Thanks for your help everyone!
Im gonna continue there. Please check my answer there
Is there a way for OnCollisionEnter to happen but prevent a physics collision?
In my case I want that for a piercing projectile, i want it to behave like other projectiles (deal damage on collision) but not collide
OnCollisionEnter happens AFTER/in response to the physics collision so no
@odd light CI/CD conversation here if you need
The one exception to that is potentially https://forum.unity.com/threads/experimental-contacts-modification-api.924809/ @elfin tree (no longer experimental)
but the normal approach would be to use a trigger collider
how would you go about doing this?
In my case I want that for a piercing projectile, i want it to behave like other projectiles (deal damage on collision) but not collide
maybe ontriggerenter still triggers for a collision on an enemy (collider, non-trigger)?
and then I just make a function and copy it to both OnTriggerEnter and OnCollisionEnter?
if u think that api is the best way i'll dive deeper into it
put both OnTriggerEnter and OnCollisionEnter on the projectile, and just switch the trigger flag on/off on the collider depending on if it's peircing or not
apparently not
also why are you calling GetComponent on the singleton when that would just return the same object?
The errors don't lie
there's nothing to do. Get rid of the extraneous GetComponent
the one without GetComponent yes
nobody said that would fix the issue. the issue is still caused by the same exact thing
PlayerHealth.instance is null
that does not mean that PlayerHealth.instance is not null
Show a screenshot of your editor with the top showing
try looking at your code and show where you see it being assigned to anywhere
Pretty clearly instance is never assigned @bleak thorn
why do you have two variables with almost the same name
it is though
It is? Ok, well i figured it would underline the double variable error
Ahhhh, one is capital 
yeah, just a terrible theme causing poor syntax highlighting
How to fix that
You set Instance to this
But you are trying to use instance
Just delete one of those
Yep, and now fix that
Set instance to this
Muchas gracias amigo thank you โค๏ธ @spring creek
how to make a physics projectile 'look towards' it's trajectory?
is there a physics way to achieve this or is this always simulated?
for example, if you imagine an arrow being shot, if it goes up and down, you'd expect the arrow to first look up and then look down
seems straight forward for a missile or something with propulsion since the force will guide it's 'look direction'
but not sure how it's typically achieved for initial velocity projectiles
there is nothing in the physics sim to simulate aerodynamics
arrows do this due to drag in real life
You have to make that yourself
the tail has more drag than the head
so there's a net torque forcing it to orient in the way it's moving.
simple way, each frame capture the previous and current positions, calculate the direction from them and then set transform.forward
or just apply the velocity as forward
For an arrow in Unity you could hack it with like
rb.MoveRotation(Quaternion.LookRotation(rb.velocity));```
in FixedUpdate
would you not normalize the velocity?
alright, and you mean it's not something you could do in the unity physics engine, correct?
yeah, not just like attaching two rigidbodies together, one with more drag
you'd be doing AddForceAtPosition or AddTorque to introduce the necessary torques
it's just... complicated. Real life physics are complicated and we're doing a primitive simulation that just looks decent
in reality drag forces are being applied to the object pretty much at every single position on the object
alright, the hack seems to be the common/simple way to do this
thx all
also i assume stevesmith's solution is equivalent to yours basically?
seems like the velocity prolly already contains that info
yep, it's basically using velocity as a direction, interesting hack, end result should be the same
Steve's solution is the same except it would directly be modifying the Transform directly. I think it's better practice to work with the Rigidbody when dealing with physics.
very true, I overlooked that
But it would be a good way to do things if we didn't have a Rigidbody available
@leaden ice would you just disable the hack being called in update when it touches the ground?
it's kinda freaking out when it touches the ground but other than that it works great
need to disable when velocity reaches approx zero
ah ye that's a simple enough check
be an interesting test, if constantly adjusting the rotation does it affect the trajectory of the object?
It doesnโt change angular velocity but may change it if forces are applied off center of mass
does not seem like rb.MoveRotation(Quaternion.LookRotation(rb.velocity)); affects the direction at first glance
what mass does your object have?
seems like somthing like this kinda works
if (Math.Abs(_rigidbody.velocity.y) < 0.1f) _orientProjectile = false;
It probably would matter more if you had an off-center center-of-mass
doesn't MoveRotaion ignore mass?
I'm thinking more of the physics calculation
I would probably do
if (_rigidbody.velocity.magnitude > 0.1f) {
// do the orientation hack
}```
for some reason it still freaks out with that code, maybe i just need a bigger float in that solution
it still rolls a bit on the ground, so i think it hits a low velocity at some point, but then it increase again
I would probably also just disable it after any collision
it doesn't make sense to do this after bouncing off the ground once I think
ye
you could also use a much larger threshold for sure
but then it might get weird at the top of its flight arc
anything particularly bad about the previous solution?
(Math.Abs(_rigidbody.velocity.y) < 0.1f) _orientProjectile = false
bearing in mind you are not going to get much deceleration but a rapid stop
it doesn't account for horizontal velocity
it will also stop working at the tippy top of the parabolic arc
ahh good point
iguess same thing but check x aswell
then that's kinda what velocity.magnitude does, no?
if (Math.Abs(_rigidbody.velocity.magnitude) < 0.1f) _orientProjectile = false;
maybe abs not needed there
probably best to make the threshold an inspector variable then you can play about with it to find the sweet spot
ye it seems to go through the ground sometimes doing this, weird
might just be a threshold thing
I'd be tempted to debug.log the magnitude to get an idea of the actual data involved
good point
magnitude seems ok
a bit of a mistery why it goes through the ground sometimes but i think i'll just ignore this for now
not the biggest of deals
(ground is just a plane for now also)
did you do as Praeter said and also disable on Collision?
ah, do you have a pivot point at the nose of the cyl?
it's just the default cylinder
and it's the child of a game object
but at the center of it
so you are rotating from the center not from the nose
worth trying
lol it goes through the ground even more reliably
i'll try to do the opposite side
hmm, same thing
maybe because
yeah that should be precluded by the if statement around magnitude
can you show the code?
now i stop on collision
i'll just check if Quaternion = Quaternion.zero first
i can share if relevant, there's not much more to it
prolly this
Should check if _rigidbody.velocity is zero or not
oh.. yeah maybe that makes more sense
Also you need both, colision disable and velocity disable
i want it to roll on the ground though
but it doesn't need to have it's rotation controlled, physics can do that for you
just in case, you dont know which one will trigger first
@leaden ice here you go
https://hastebin.com/share/elosimazeg.csharp
Hastebin is a free web-based pastebin service for storing and sharing text and code snippets with anyone. Get started now.
i mean in that case it will always go through the ground but that was another test i was doing
without the .isTrigger part, only some of the time
reading that line was like ecstacy
so much quaternion talk in one message
i guess u figured out i don't understand them at all x)
Okay so after an hour of testing cuz I'm a noob, if I set up a scriptable object for MovementParameters I found out that yes I do need to create a new scriptable objects for each things that calls for MovementParameters movementParameters. Cool, understand that I think. I'm trying to learn scriptable objects and how to implement them in to my game while I'm in the early stages.
But this brings me to a new problem. Let's say I make a basic enemy like a Goomba, and in its script it's calling for the HealthManager Scriptable object. Then I spawn 4 Goombas. Now they're each SHARING health even though they're all new instances of the enemy prefab, because they're all referencing the same HealthManager_Goomba. What's the way to handle this?
Just did a very quick read, but are you directly modifying the values from the SO in scripts?
Ummm, so let's see, here's my HealthManager:
using UnityEngine;
[CreateAssetMenu(fileName = "HealthManager", menuName = "ScriptableObjects/HealthManager")]
public class HealthManager : ScriptableObject {
public int maxHP = 100;
public int currentHP = 100;
public int healthRegenRate = 1; // Health regenerated per second
private float healthRegenTimer = 0.0f;
public void TakeDamage(int damage) {
currentHP -= damage;
currentHP = Mathf.Max(currentHP, 0);
Debug.Log("Player took " + damage + " damage, current HP: " + currentHP);
if (currentHP <= 0) {
Die();
}
}
private void Die() {
Debug.Log("Player has died.");
// Add death logic here (like triggering animation, disabling player control, etc.)
}
public void RegenerateHealthOverTime() {
healthRegenTimer += Time.deltaTime;
if (healthRegenTimer >= 1.0f) {
int healthToAdd = healthRegenRate;
currentHP += healthToAdd;
currentHP = Mathf.Min(currentHP, maxHP);
healthRegenTimer -= 1.0f;
Debug.Log("Player regenerated " + healthRegenRate + " health, current HP: " + currentHP);
}
}
public void RegenerateHealth(int amount) {
currentHP += amount;
currentHP = Mathf.Min(currentHP, maxHP);
Debug.Log("Player regenerated " + amount + " health, current HP: " + currentHP);
}
}
@red dust That's the issue
You 'never' want to directly change the values of a scriptable object through code
if (velocity != Vector3.zero) _rigidbody.MoveRotation(Quaternion.LookRotation(_rigidbody.velocity));```
This should be ```cs
if (velocity.magnitude < threshold)```
Hmm I see, so then in the EnemyStats script when it calls for a health manager, I need to store the stats separately there?
I'm not quite sure the best way to go about it but I typically will treat what your healtmanager is as "HealthManagerData" and then have another class (HealthManager) with a constructor that takes "HealthManagerData" as a param
also i would probably have the health in an enemy/characters's scriptable object instead
This isn't really what ScriptableObjects are for. They're not really for mutable data if you're using them in this way
if you want to store things like max health and regeneration rate in the SO that works
but the current health for an individual enemy should live on the enemy itself
will give that a try
Hmm I see, I'm still really new to coding and I was told to try to SOs to compartmentalize things. Currently I don't even have enemies, just a player that's calling for a HealthManager and ManaManager, then a scriptable object for each
SOs are to store and configure data in nice little assets in the unity editor that can be referenced in the editor
not really sure how that relates to "compartmentalization"
classes in general are for encapsulization and compartmentalization but SOs are a very specific/special thing
yeah another way to look at it is SOs are often for 'content', so enemies, projectiles, items (they can do other things too though)
different configurations
You can certainly use SOs for mutable data but you'd have to actually understand how they work and be a bit more advanced of a programmer to use them that way
Like I said I'm a noob so probably the wrong term then. I have a player controller for a platformer that's running exactly how I wanted, so I wanted to refactor/clean up/make it easier to expand upon before I got to work on the spells
im using Input.GetAxis("horizontal") and the value for it keeps increasing does anyone know how i can make it only increase or decrease when either the "a" or "d" keys are pressed (2D)
i think what you call health manager should be part of either the player or an enemy or both
and just be a standard class or monobehaviour
then you'd have an enemy SO to configure your enemy, and hp from it would be used to generate ccurrenthealth in your healthmanager's instance inside the enemy
i might be explaining this poorly though
(enemy could also be player in that explanation, or whatever it is)
What do you mean by "the value for it keeps increasing?" Where are you seeing it increase? What are you doing with it? Show your code?
(2d is irrelevant here)
float horizontalInput = Input.GetAxis("Horizontal");
float verticalInput = Input.GetAxis("Vertical");
Vector2 direction = new Vector2(horizontalInput, verticalInput);
rb.MovePosition(rb.position + direction * speed * Time.deltaTime);
animator.SetFloat("left", horizontalInput);
animator.SetFloat("right", horizontalInput);
animator.SetFloat("down", verticalInput);
so what do you mean by "the value for it keeps increasing"?
im using it in animations to get the sprite to change when you walk or turn in a specific direction
also !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.
@leaden ice going back to the isTrigger for piercing projectiles, lets say i still want them to collide with the ground, i'm currently going for having a 'pre-ground' trigger plane to turn isTrigger back off, makes sense?
oh my bad
That's what it basically all is right now in mono behavior with some interfaces/abstract classes for my spellcasting mechanic. I was just trying to get ideas on how I could do things differently. In my player code where I was setting up movespeed, accelerationTime and decelerationTime, I tried changing it to call for MovementParameters SO, and hooked that up to see how scriptable objects work
animator.SetFloat("left", horizontalInput); animator.SetFloat("right", horizontalInput);
Why have two params that you're just setting the same value to?
the value i am using in the animations tab
it looks nices in the animations area
no you should just use layer-based collisions.
Show what you mean.
but then it would completely ignore the 'collision'(trigger collision here) on an enemy (currently it's OnTriggerEnter)
Two colliders:
- One trigger
- One non trigger
on two different layers.
Set the layers and matrix up appropriately when needed in order to have the desired interaction happen
whenever i change directions in the game the value of "left" decreases bellow -0.01 even when no button input is being pressed
sounds like you have a joystick plugged in
i dont own a joystick
gamepad perhaps
bellow -0.01
Show an example of this?
i.e. xbox or playstation gamepad
it has now stopped changing when nothing happens but now decreases to bello -0.01 when i press the down input
but its the horrizontal value
so "below -0.01" is a really weird thing to say
ye ye, was just trying to explain the when to use them
im not explaining this very well
can you just show some screenshots or a video already
it would make this so much easier
i want the image to change when i press the a key which it does as it changes the value left to -1 but left also changes to -1 when i press the s key which it shouldnt
i do not have video softwhere on this laptop sorry
sounds like you either have a bug in your code putting the value in the wrong place, or you went into the input manager and changed the key bindings on some of the axes
Hi guys, does anyone knows is it possible to make game object name or little cube icon of different color like it is for prefab, or any other way to make some game objects in hierarchy tree view being distinguished from others?
not a coding question, but i think you're talking about icons?
Would something like this also prevent physics collisions with Enemy?
if you want something like changing the color of text in the hierarchy, there are asset store packs you can download that do that
@leaden ice @knotty sun In case you guys are curious, setting the collision detection to continuous dynamic fixes the going through ground thing, might be horrible for performance but I don't know yet!
This question might be too general, but I am making a demo game where the player moves around a planet (or, small sphere, similar to mario galaxy), but I don't really want things like escape velocity or orbit to exist. Instead, I want the player to essentially be "stuck" to the planet, and holding W (or forward on controller) would result in the character circumnavigating the object. As of now, if I move too fast over the curvature, my player will fling off. I can counter this by increasing my gravity (which pulls toward the center of the planet), but it messes up movement since it's pulling so hard.
What's a good way to A. translate movement so that it feels like the planet is spinning under you while moving (like those rolling log competitions) and B. create gravity that doesn't feel like realistic physics, but just keeps the player grounded? I could just rotate the planet under the player, but I want to incorporate a spin on the planet's axis so I can have realistic day/night cycles. In addition, this won't work as it will really show that that's what I am doing when I start having other planets/things in the solar system.
are you doing 3d?
if so, one thing you could do is use spherical coordinate. apply your movement input as acceleration/decelration to angular position, and keep the radius constant.
if you want the player to go up down (i.e., farther/closer to the planet), you can apply a similar acceleration to radius as well, perhaps even clamping the radius to some limit of your choosing
up to you whether you want that to be a separate input as the forward/back.
or if you want to do some kind of... dynamic radius adjustment based on speed or whatever. that's where you'll have to do some experimentation.
I might've lost you here, haha. It sounds like you're saying calculate the vector perpendicular to the planet's normal and apply velocity with that vector?
just use a spherical coordinate system with the planet's center as your coordinate system's center.
you need a conversion function for Euclidean coords to those spherical coords and back
you can look those up on the web
then all you do is take your object's transform.position, convert to spherical
then if you want it to go around the planet, apply some change to the theta and/or phi angles
if you smoothly adjust, say, theta, from 0 to 360, with wrapping, the object will essentially orbit the planet
after each adjustment to spherical, convert back to euclidean and paply it to your object
Got it. Thanks! Gonna go research all of that, haha!
here's a really rough example
setting radius doesn't work because i didn't do that part right but you can see the orbit works. you'll probably have to play around with it and refine it to get exactly what you want
Hastebin is a free web-based pastebin service for storing and sharing text and code snippets with anyone. Get started now.
https://blog.nobel-joergensen.com/2010/10/22/spherical-coordinates-in-unity/ code for coordinate transforms was taken from here
Oh, sick! Thanks again so much! You really didn't have to do all of that
Could someone help me figure out why these two float values hpLost and percentLostCheck are evaluating to false when asked if they are >= and they both have a value of 0.2?
you'll also have to adjust this for the position of your planet, as this code assumes the planet is at the origin of unity's coordinate ssytem
have fun
because you are seeing the rounded string value of the variables. internally they may not be exactly 0.2
would a better method be
(hpLost - percentHealthCheck >= 0) ?
probably better 0.01f or something similar
lets say I have a rigidbody that's already moving normally, what physics function could i use on it lets say a piercing projectile goes through it to make it either stutter or slow down a little bit, with no regards to where the rigidbody is going or the projectile direction?
hopefully it would be visible
but also not really hindering to the rb
(that's a bit of hail mary but who knows)
you could get the contact point of the collision and add a force at the position
it's a trigger enter so all i have is a collider
then you would need a raycast to find a hit point
it's physics based projectile so i don't exactly know where it's gonna hit, unless you mean raycast on trigger enter?
but yeah addforce is prolly the better way to go about it
just not sure how exactly i'll do it
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Oculus.Platform;
using Oculus.Platform.Models;
using PlayFab;
using PlayFab.ClientModels;
public class IAPChimp : MonoBehaviour
{
[SerializeField]
private Playfablogin playfablogin;
public string SKU;
public int Amount;
public Material normal;
public Material pressed;
public AudioSource sfx;
private Renderer render;
private void Awake()
{
render = GetComponent<Renderer>();
render.material = normal;
Debug.Log("Initializing Oculus Platform...");
Oculus.Platform.Core.AsyncInitialize("OCULUS_DEV_KEY").OnComplete(OnPlatformInitialized);
}
private void OnPlatformInitialized(Message<Oculus.Platform.Models.PlatformInitialize> msg)
{
if (msg.IsError)
{
Debug.LogError("Oculus Platform initialization failed: " + msg.GetError().Message);
}
else
{
Debug.Log("Oculus Platform initialized successfully!");
}
}
private void GetPurchases()
{
Debug.Log("Getting viewer purchases...");
IAP.GetViewerPurchases().OnComplete(GetPurchasesCallback);
}
private void GetPurchasesCallback(Message<PurchaseList> msg)
{
if (msg.IsError)
{
Debug.LogError("Error retrieving viewer purchases: " + msg.GetError().Message);
return;
}
foreach (var purchase in msg.GetPurchaseList())
{
if (purchase.Sku == SKU)
{
Debug.Log("Matching SKU found in purchases. Adding currency...");
CurrencyAdd();
IAP.ConsumePurchase(SKU);
}
}
}
public void BuyIAP()
{
Debug.Log("Initiating purchase flow...");
IAP.LaunchCheckoutFlow(SKU).OnComplete(BuyProductCallback);
}
private void BuyProductCallback(Message<Purchase> msg)
{
if (msg.IsError)
{
Debug.LogError("Error during purchase flow: " + msg.GetError().Message);
return;
}
Debug.Log("Purchase flow completed successfully. Retrieving purchases...");
GetPurchases();
}
public void CurrencyAdd()
{
Debug.Log("Adding virtual currency...");
var request = new AddUserVirtualCurrencyRequest
{
VirtualCurrency = "OR",
Amount = Amount
};
PlayFabClientAPI.AddUserVirtualCurrency(request, OnAddCoinsSuccess, OnError);
playfablogin.GetVirtualCurrencies();
}
void OnAddCoinsSuccess(ModifyUserVirtualCurrencyResult result)
{
Debug.Log("Virtual currency added successfully.");
playfablogin.GetVirtualCurrencies();
}
void OnError(PlayFabError error)
{
Debug.LogError("Error adding virtual currency: " + error.ErrorMessage);
}
private void OnTriggerEnter(Collider other)
{
if(other.tag == "HandTag")
{
Debug.Log("Hand entered trigger. Clicked Button...");
sfx.Play();
StartCoroutine(resetColor());
if (playfablogin.loggedIn)
{
Debug.Log("User logged in. Initiating purchase...");
BuyIAP();
}
else
{
Debug.Log("User not logged in. Purchase flow aborted.");
}
}
}
IEnumerator resetColor()
{
render.material = pressed;
yield return new WaitForSeconds(0.1f);
render.material = normal;
}
}
can somebody help me make it add the SKU name to the player's playfab inventory on purchase?
what i got so far
var impactPoint = other.ClosestPoint(transform.position);
var forceDirection = other.transform.position - impactPoint;
var forceDirection.Normalize();
forceDirection **= -1f;
other.GetComponent<Rigidbody>().AddForce(forceDirection * IMPACT_FORCE, ForceMode.Impulse);
ah that seems better
i might not have to change too much
yeah looks better i think
thanks
Does anyone how to fix this issue, the camera movement has some insane snapping, ive tried change where its processed from update to fixedupdate to lateupdate
why would you move it to late update or fixed update
that made it worse
ive tried all 3 options and its still the same result
you should probably share the original code since guessing is not very helpful
2 issue I'm seeing
1 mouse should not be multiplied by Time.deltaTime
why are you doing player.forward.rotation? instead of just player.rotation
is camera child of the player ? you can get rid of the yRotation on the mouse
forward is the name of a transform on player where i do stuff
what?
player is a component that has a public transform called forward
no, multiplying mouse input by deltaTime is not correct, even when using GetAxisRaw
smoothdelta time makes it a bit better
ah ok good to know thanks for clearing
nahh its wrong
i bet your issue is both y rotations are not sync
parent cam to player and remove yrotation on cam
i think also the display resolution might be something too
i tried too removing the player from it and just having the raw camera movement
not having part of the script where i move the camera, only rotate it
can you show your current code after changes
i just removed the transform.position part of the script
ok that was only part of the problem
did you get rid of time.deltaTime on mouse?
turn down the sensitivity after cause it will be high
i think the issue is the mouse input
and sens might be too high too yea
Ok i figured it out, it was because i had an enemy that was updating the navmesh every second causing a lag spike
๐คทโโ๏ธ
also the time.deltatime has no reason to be there
thanks for all the help, now instead of having 400 sens its a solid 3
Escape velocity only exists because in the real world, gravity diminishes with distance.
I'd recommend keeping things simple, but it's up to you !
Haven't found a section about profiling but maybe just didn't search enough?
Is there a way I could know what exactly causes this spike? Like what gameObject or Mesh?
try deep profiling
it's on, i thought that's all i needed to do?
I did find that:
trail renderer maybe^
i'm not as lucky for the other spikes though
depends it says on the top spike u got at least 50k tris
are u sure its not a very expensive mesh
where did you see the tris?
i wonder what could even have that many tris, i'm pretty much only using primitives
iirc unity tries to batch them into one mesh
i have some svg icons i turned into meshes but they are rather simple
oooo
could explain
esp if you have same material / static
alright, well i guess there's nothing too bad there?
seems like the trail renderer was performing horribly
which i feel like that<s prolly why most people avoid using it
also how many tris is too many?
i don,t have many draw calls but I could get away with leaving up all the projectiles that were shot
it gets a bit crazy but doesn<t seem to cause lag which is what i would<ve expected
prob millions
interesting
ofc depends on target platform too
yeah makes sense, mobile would be fun but i'll worry about it if i even get there
private void OnDoubleClick(PointerEventData eventData)
{
RectTransform mapPanelRect = mapPanel.GetComponent<RectTransform>();
Vector2 localPoint;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(mapPanelRect, eventData.position, miniMapCamera, out localPoint))
{
MapController.instance.SetDestinationMarker(mapPanel.transform.TransformVector(localPoint));
Debug.Log($"MiniMapController: OnDoubleClick: evenData.position {eventData.position}" +
$"\nlocalPoint {localPoint}");
}
}
I'm so stuck XD
I'm trying to implement a minimap with an orthographic world space camera and a 10,000x10,000 canvas group. But I can't figure out how to calculate for the local position of the players click relative to the canvas group, when the player clicks on a raw image that is displaying the minimap camera
so you're trying to get the position from the phone map as coordinates on the main map?
so, let's assume the pivot is bottom left of your map, so make the phone map pivot also bottom left. Normalize the units of your screen such that you can calculate a position from the pivot and apply that offset along with the camer's pivot
So, say top right of the screen is 30x, 30y, and you press the center so you'd have a screen offset of 15x, 15y, then add that onto your camera pivot that could be at say -300x, -500y, and add the map's offset value to that for your world point
I would change to local after if you need to, but I'd stick to world values if you could
well, the camera map would be screenposition normalized as unit values from its pivot (actually local values on the phone would be fine too)
Does someone know why this isnt working?
Missing a semicolon up top. As your error says, line 4
!ide
If your IDE is not autocompleting code
or underlining errors, please configure it.
Select one:
โข Visual Studio (Installed via Unity Hub)
โข Visual Studio (Installed manually)
โข VS Code
โข JetBrains Rider
โข Other/None
Just wanna say thanks again for the help earlier! Ive done a bunch of tweaking to figure this out and how I want to implement it, starting with my player stats and stuff. Im gonna put my thought process here so any feedback is always appreciated!
For example I made a HealthParametersSO scriptable object that only holds a maxHP and an hpRegeneration rate, as well as an IHasHealth interface that only specifies TakeDamage() RegenHealth() and RegenHealthOverTime functions.
Then I have a HealthManager script inheriting from IHasHealth and calling for the HealthParameters, internalizing the maxHP and healthRegenRate, and making use of the functions from IHasHealth.
Now if I make 4 different enemy prefabs, give them each the HealthManager, and attach a HealthParametersSO_OneForEachEnemy to it, they should all work the way Im thinking right?
Any bullet with some damage number could find the HealthManager of any object it collides with, and use the TakeDamage() function in that instance.
I hope Im thinking about all of that right. I figure my Player and Enemies will all use essentiallt the same "Has Health, Takes Damage, Regenerates Health" needs, so this seems like the right way to easily make things modular and expandable
Okay so now i cant drag the countdownText down, but other text i can do
Is countdownText a TextMeshPro object?
yes
You declared it as Text
So that is why it doesn't work
TMP_Text is what you want
float projectileDamage = 10f;
private void OnTriggerEnter(Collider collider)
{
//is true if target is part of a gameobject with a script/component that implements IHasHealth
if (collider.TryGetComponent(out IHasHealth target))
{
//call TakeDamage which is implemented with IHasHealth
target.TakeDamage(projectileDamage)
}
}```
Yes, exactly how Im hopijg to do it, I have a ProjectileSpell abstract class my spells inherit from, so I expect to put it there. Otherwise, does my logic sound right? Like Im using the idea of interfaces and scriptable objects pretty much correctly?
I treat SOs as the guts of an object such that my Enemy class has parameters (if you could use constructors with monos) that require EnemySO which defines their starting health, damage, ect.
Technically I only need a single Enemy prefab if the guts define everything such as rendering/sprites
That's exactly how I do it
Sweet, thats exactly how I put it for now. My HealthManager is taking the definitions from the SO and messing with them, so that if I attach it to the player or different enemy prefabs, they all should function properly. Im slowly trying to tweak the basic mechanics I have set, now that all the movement and casting feels right, before I expand, so Im glad I seem to have the right idea so far
Can always skip out on the rendering idea and define more Enemy prefab objects which is another idea
when it comes to pooling though, you usually want to minimize the prefabs
Player object, slap a health manager, enemy? Slap a health manager. Breakable barrel, slap a health manager. If it works how I think its going to, Im glad Im taking the time to refactor my code into these bits before I really get into the deep end
Next is gonna be breaking some of my players movement code out like this, so I can possibly reuse bits for other things. Like taking moveSpeed and accelleration/deceleration time from the main player scripts, and making them SO and setting up interfaces so that anything that ever needs to move can use those same bits
Just curious, would it be wrong or make much of a difference if instead of GettingComponent IHasHealth, we got the Component HealthManager? Does it matter, is it a best practices thing, I just wanna clarify xP
The whole point of an interface is for moments like that. You shouldn't care if it is HealthManager or SpecialCaseHealt, they both inherit from IHasHealth, and both have TakeDamage
So creating a new component that implements IHasHealth means no change in code, you just slap it on and it works
Interfaces can help two ways with this. For one, you can add it to different classes so say you have a IMovement interface, but you have two different methods for movement between your Player class and your Enemy class. Navmesh agent for the enemy, and physics for the player, so when you call ReduceMovement*(float amount) method it will do its own different operation depending on the type that this interface is bound to.
Ahhh so i should keep it to IHasHealth, so that if I make another thing like HealthManagerBoss, all the references work. I wasn't thinking about that cuz I figured I wouldn't really implement IHasHealth anywhere else, but that makes sense now
The other way interfaces can help is it only exposes the properties and methods that you are meant to interact with, so your IHasHealth will not make your movement speed fields on your character's exposed when accessed.
So, another example is you have IEntityStats that has both Health and Movement speed, but by dividing it up into two interfaces, IHasMovement and IHasHealth, you can pass those interfaces around without exposing properties that should not be touched some of your logic
float projectileDamage = 10f;
float slowAmount = 10f;
private void OnTriggerEnter(Collider collider)
{
//is true if target is part of a gameobject with a script/component that implements IHasHealth
if (collider.TryGetComponent(out IHasHealth target))
{
//call TakeDamage which is implemented with IHasHealth
target.TakeDamage(projectileDamage)
//Error: cannot access SlowMovement from IHasHealth
//target.SlowMovement(slowAmount);
//Alternative, check by IEntityStats to expose both TakeDamage(), and SlowMovement
}
}```
Hmmm...I think I'm understanding a bit xD
interfaces let shit have stuff in common, without forcing them to derrive from some common garbage
how many things actually implement this interface? if only one thing implements it ever, the interface itself doesnt really need to exist. Something like health is always done the same way
There is some public take damage function, then the health script calculates its new health. You attach this script to anything that has health. Its rare that something actually needs to calculate health in a new way. You can treat a rock and an enemy the same, its just on "death" that you handle it differently.
you can have 10 classes that all implement IDamageable without them having anything in common with each other. But then you can make functions that operate on IDamageables that only require the few features that they actually have in common.
While what the function actually does is totally different, because itโs an interface.
IDamageable as an interface might only have the method defined: public void TakeDamage(int damage)
that is it, and so that is all which must be satisfied for a class to implement IDamageable
im curious as to how many people actually have more than 1 override for TakeDamage. I find interface completely unnecessary here
whether that class is a player, a chair, enemy, bullet, etc does not matter
pretty useful for some of my Damage functions, some of them take in a Direction when its a ray
The idea is that anything that can be hit with an attack and take damage IHasHealth for maxHP and hpRegenRate managed by the HealthManager, whether it's the player or a breakable object or an enemy. So I give whatever object that is a HealthManager, and anything that would hurt it can just access the IHasHealth.TakeDamage(int amount). Maybe I'm not explaining it right or maybe I am and I'm just doing it wrong still xP I'm new to this so I'm learning as I go right now lol
also, you normally want to name an interface in a way that describes what you can do to it
So basically my IHasHealth should be more like IDamagable
yes, that would be more normal
because having health isnโt the same as being damageable. and if something takes damage, the class that implements IDamageable can figure out wtf it wants to do with this information
maybe a chair is IDamageable, but has no health. It takes dmg and then instantly breaks
I understand the use of interfaces, i am just claiming you probably dont need it if you dont actually plan for things to take damage in a unique way. It sounds like you plan to use a HealthManager for anything that can take damage. This would make sense if you had another script like
BreakableObject : IDamageable but even in this case, I would just throw a health manager on the object and give it 1 hp
maybe a player is IDamageable, but when it takes dmg, you need to check invincibility frames, and trigger gameover etc
If you start providing this functionality on other scripts like player, rock, enemy, you run into cases where the scripts are already implementing these so you cannot have a rock with hp and one without.
What i am saying is basically you are going to combine composition and inheritance in this regardless, the interface isnt really needed
That was my idea, just set any HP case by case whether it's a big thing like a boss or a box on the floor.
Renaming it, my IDamagable would keep its TakeDamage() but, and I guess I should move the RegenHealth() and RegenHealthOverTime() to a different interface, like IHealable?
Player, enemies, maybe a structure that's being repaired as you try to break it, yeah I figured I'd need multiple things that can heal
๐คทโโ๏ธ depends on again if you need this interface. Like in what case are you ever gonna call GetComponent<IHealable> and actually expect different implementations? In what case are these objects ever gonna heal in different ways, we are just adding numbers here
in my game, i have IRadiatable (things that are affected by radiation), IBlastable (things affected by explosions), and IFlammable (things affected by fire). If it is a player class or something, the player class can figure out that if one of those functions is invoked, it can call its own TakeDamage function
but then I can have some objects that just get yeeted via their IBlastable interface, or some objects that crumble and get destroyed via IBlastable
since you write the whole interface implementation every time, each implementation is totally different, separate, unrelated
my blast zone monobehaviour finds objects in the blast zone, then calls GetComponent<IBlastable>(), and if the object has a monobehaviour implementing IBlastable, it invokes the IBlastableโs OnBlast(Vector2 position) method
blast zone monobehaviourโs job is complete. wtf the object wants to do with the information (that it is in a blast zone) is not its responsibility. Blast zone just lets everyone know that they are in a blast zone from a given spot.
does this make things a bit more clear?
Honestly I must be misunderstanding something important, so let me see if I can break this down to see where I'm having trouble.
An interface IDamagable is made for anything that would need to take damage by something else calling for its OnDamage() method
So my Player, Enemy, and a random Breakable box all have their own HealthManager that inherits from IDamagable.
if something calls for their GetComponent IDamageable.OnDamage like a bullet hitting the enemy, it sets off the OnDamage() function, which is specified on that enemy/player/box's HealthManager
That's how it's supposed to be used, right?
Or do I specify the OnDamage function specifically somewhere else, since they'd all use the same calculations in the end
Does Unity support HTTP/2.0? ( Mono Runtime )
(Also in this example, it's the same HealthManager with the same OnDamage() methods, given individually to each object)
Thank you btw for taking the time to explain, I'm sure this is frustrating xD
Yes this is what would happen, they would all be doing the same thing.
do I specify the OnDamage function specifically somewhere else
This is up to you if you want them to do different things. But you need to be careful about where you implement this interface though. In this case you'll need like a BoxHealthManager or whatever you wanna name it, which I find will likely be unneccessary. I will explain why with a scenario
Lets say you have a box that can break and a box that cannot. Both boxes can be opened to find loot so they both have some Box script on it. You cannot implement IDamageable on this Box script, because 1 box cannot be damaged. You need to implement it on another script, like BoxHealthManager and attach this script to the box. Ok now what difference is there between HealthManager and BoxHealthManager. Nothing. The only difference is when the object dies, a player would die, a box may shatter. This can all be solved by having 1 HealthManager script with a death event. Any other script can subscribe to that death event then do what it wants
That's exactly how I have it. ONE HealthManager script, like I said
This is how I have it as well. I find interfaces here unneccessary
In this example, the box script would handle opening I assume. Then if one box should break but the other shouldn't, the breakable box also gets the HealthManager script, was my idea anyway
this is how I would do it as well
Now if you truly plan for something to take damage in a unique way, then it would make sense to use a IDamageable interface. Like an enemy that heals when damaged instead (idk how you will kill it).
even in this case, I wouldnt make a 2nd health script. I would have some other script handle this by changing the damage number. But this requires more setup like I have items and effects which are considered before damage is applied
I think what I'm getting here is that I have the right idea generally, but you thought I was doing something else that would've been a bad way to do it.
I was never planning on making a second healthManager script, I was trying to make it the way that I am so that I could reuse that same script across basically anything that would need to track its own health
Or, you're saying to just cut out the IDamageable interface, and just put that code directly into the Health Manager
interfaces shouldnt really have any code in them, just a declaration of the method. But yes I am saying you can cut it out with no difference.
There are other cases interfaces will be more valuable, lets take the IBlastable method mentioned by Loup&Snoop. You cannot just have 1 implementation which works, because not all objects move the same way. Simplest example of this is a rigidbody and a character controller
can anyone with some knowledge of DoTween help me out?
private void Update()
{
if (target != null)
{
Vector3 newPos = cam.WorldToScreenPoint(target.position + new Vector3(0.0f, targetCollider.bounds.size.y / 2 + offset, 0.0f));
child.position = newPos;
}
}
private void OnEnemySelected(Enemy enemy)
{
target = enemy.transform;
targetCollider = enemy.GetComponent<Collider>();
child.DOLocalMoveY(child.localPosition.y + 5.0f, 0.2f, false).
SetLoops(-1, LoopType.Yoyo).
SetEase(Ease.InOutQuad);
child.gameObject.SetActive(true);
}
I m trying to make this Ui element stay on top a selected enemy and do a little Y tween over it. but the tween is super irregular and sometimes go very high up there, other times doesnt move at all. very weird, i tried with a bunch of different numbers already
Its starting to really make sense now. Yeah right now my interface just holds the declaration of TakeDamage() and then I let the HealthManager determine that calculation. If everything is going to take damage the exact same way, which I assume it generally will, then cutting out the middleman with the interface and putting those methods directly into the HealthManager seems to make sense in the spirit of cutting out the extra fat.
I've seen lots of examples of people declaring things in an IDamageable and then using that for both enemies and player calculations in their managers. So that's just basically redundant is what you're saying?
I understand how it would be more useful for a setup where different things behave differently based on the same feedback though.
yes it is redundant. when considering an enemy or player, they are both just characters. both will have stats at the end
So I'd only make the interface if, say for some reason the enemies and the player take damage on a different scale from each other, so that the Player script and Enemy Scripts could each hold their own calculations?
But in my scenario, since everything that has Health to be manipulated just has a copy of the HealthManager, setting OnDamage there is literally the same but cleaner?
you use interfaces to ensure common functionality. So two classes that will have the same function, done in a different way perhaps will implement the interface and they can handle the logic on their own
With components you as defining one way of dealing with a certain thing, for all the objects that need to deal with it
if you are going for components, no need to go for interfaces
But since I'm only using the IDamageable interface in my HealthManager script, and not in any other class, it's just extra to have it there, and should all be in the HealthManager instead of the Interface?
Do I understand that correctly now?
yes, delete it
Okay okay, cool, I think I got it. I had the right idea and am on the right track, but I went an unnecessary step further with the Interface
are you using the correct position here? you seem to get the enemy's transform and collider without using it at all
shit, i think you are right
a very necessary step to understand the problem you are solving
people may see it as cleaner to have that interface inbetween, incase you decide to implement it differently in the future. In my case, i am absolutely certain I will not need it
in some cases too, i opt for abstract classes instead of interface just for sake of serialization
That's probably how I got around to having it in the first place. Somewhere recommended having the interface just as a standard.
Abstract classes are another thing I'm still getting used to. Separately for handling my spells, I have an Abstract Class called SpellBase that all my spells take from to perform their unique effects, but that's another area I'm not entirely sure I'm doing correctly in the end xD
Bwahaha yeah I get that xD luckily, as it stands all my code works pretty much exactly how I want. Right now I'm trying to refactor and streamline what I have so that expanding in the future is easier, hence the Scriptable Objects and Interfaces at the moment
I'm using an Interface ISpell that declares OnCastPressed, OnCastHold, and OnCastRelease methods, and then my SpellBase Abstract class is inheriting from ISpell, and each final spell is inheriting from the SpellBase. Idk if that's stupid or not tbh but it's working rn xD
(In the spirit of the naming conventions you guys explained, ISpell will probably change to ICastable or something)
An advice. Take a look at your code an use an app like draw.io to put it down and look at the bigger picture, then check if you can improve stuff
Think about it, if a spell is already a spell, is it ever not going to be castable? Do you need that interface?
I thought yes, because each spell casts differently? Like one would be a projectile that shoots OnCastPressed, while one would be a shield that stays active OnCastHeld?
are they still not all castable? You should have an abstract class Spell, then other classes AoESpell, HeldSpell, SingletargetSpell...
Cast should be an abstract virtual function
are you going to be able to cast other things? like items or mounts or something?
Another approach is to use ICastable on alls that castable and also using that to hold what castable is in a hotkey bar for example
Interfaces separate what a thing should do and what a thing is
In my general plan yeah, the spells are going to have really varying effects from spawning to firing to like teleporting the player
arent they still spells in your plan?
Okay so convert the interface ISpells into an abstract class Spells.
Then let's say I have Projectile Spells and Melee Spells, I'd make those classes that each inherit from Spells, right?
One step further, if Projectile spells is my base for those kinds of spells, I would then make a MagicBoltSpell that inherits from Projectile spells, and gets everything it needs, with the ability to add unique functionality to that specific spell there?
Yes, exactly
Wow, okay so it seems like I was doing things right, just with the pieces all backwards xD
If MagicBolt doesnt have anything unique that needs to differ from a ProjectileSpell, then you dont even need that
I figure ProjectileSpell wouldn't be a thing that's ever called, even if a MagicBolt and a FireBolt are basically the same thing with different numbers, they'd each have their own class pulling from Porjectile spell
Thats just complicating things
Thats a step too far
You can create a Scriptable Object that hold information about what happens when a spell collides, and create instances of it for MagicBolt and Firebolt, for example
Hmmm...lost me again xD
you understood where i said thats only complicating things, right?
In my scenario, I just want Projectile Spell to just be the base that all my projectile type attacks would use, not actually use the projectileSpell abstract by itself, or that's how I was picturing it
projectile spell shouldnt be an abstract
Since I'm planning on varying my spells, I figured even a firebolt and a MagicBolt would have enough of a difference that they'd be their own script calling from projectilespells
only spell should be an abstract, avoid double inheritance always
Hmmm okay
projectile spell is already a type of spell. no need to take it further
Somehow to me, breaking it up that way sounds more confusing than how I was doing it
-Abstract Spell give the OnCastPressed,
-Projectile Spell turns that OnCastPressed into firing the spell, and then
-MagicBolt/FireBolt determines what exactly is firing and any special properties that specific spell has like an elemental type or a damage number
no AbstractSpell just gives CastSpell()
ProjectileSpell defines how exactly that happens
MagicBolt and Firebolt dont exist.
those are just prefabs
with data
My original implementation of my ability system was like this, but eventually went more modular and made these behaviors enum specific
it was dividing a lot of my logic from my other ability types which I wanted to use too
In that example, let's say I need the projectileSpeed and a detonationTime (if lets say that specific spell can explode) then I can make a SO that the projectile spells reference for those variables, then on the prefab for MagicBolt, I'd give it the Projectile spell Class, and plug a MagicBoltParameters SO into there?
This probably isn't optimal I'm sure, but that would work that way?
Composition is more useful than OOP with these types of systems unless you're completely set on your design
getting this error where in an enemy class i try to access a key from an enemystats dictionary
private void Start() {
StartCoroutine(LateStart(0.5f));
}
IEnumerator LateStart(float waitTime) {
yield return new WaitForSeconds(waitTime);
float scale = enemyStats.stats[StatNames.SightRadius];
sphere.transform.localScale = new Vector3(scale, scale, scale);
}```
but its not actually there when i debug, even though when i instantiate the dictionary it correctly runs through every enum i specify ```c#
public class Stats : GenericDictionary<StatNames, float> {
public Stats() {
foreach (StatNames stat in Enum.GetValues(typeof(StatNames))) {
Add(stat, 0);
}
}
}```
anyone know why this happens
I'd start throwing down breakpoints, and checking that the dictionary is being populated and that you're accessing the correct one.
execution ordering, ect
i used a breakpoint and found that the dictionary's keys stopped right before sightradius
but i put a debug.log in the stats constructor and it ran through all enums
so its very confusing
Kinda hard to say anything with the limited info. You seem to be using some custom types like GenericDictionary that we know absolutely nothing about. It would've been a bit more straightforward if you were using standard types.
its just a dictionary where i can update the values in the unity editor
Okay, well, then how does it play with a constructor? When is the constructor run? Does it override the values defined in the inspector..? There are many unclear points.
constructor is run before the game starts and inspector values overwrite the values set in the constructor
So, there's no point showing us the constructor, as the final dictionary might as well not have the keys it was constructed with?
Well, you said that the inspector takes precedence
Just a note, this late start seems like a horrible idea and suspectible to bugs.
And we don't know your implementation of the generic dictionary, since you never showed it.
yea i thought the problem was from the player detection class trying to call on the dictionary before it was populated but evidently thats not the case so ill remove it
Execution order shouldnt be solved by random delays. You can always initialize everything you want in order
Start debugging from the end: confirm that the key is not in the dictionary right before the error. Then go to where the key is supposed to be added and make sure that it's added correctly. If it is, go to every place the dictionary is modified and see if the key is removed at that point.
The basics of debugging...
Hey quick question, anyone know what the issue is when a variable is visible in the inspector but won't let you put anything it in?
that's not very specific
Is it grayed out?
but if i had to guess, you are probably trying to drag a scene object into a prefab which isn't allowed
Trying to make a score counter with TMP pro, got the code all set up and it should work, it's the same as a lives counter I made that does work just with a few names swapped out yet whenever I try to assign the text that the code updates, it just doesn't accept it
then either your variable type is wrong, or i was right and you are trying to drag a scene object into an asset which you cannot do
So I can't just drag the text item from the scene manager over to the variable directly?
is the text object in the scene and the object you are trying to drag it onto an asset?
yes, that is a prefab which is an asset
assets cannot refer to in-scene components at edit time
https://unity.huh.how/references/prefabs-referencing-components
did you bother clicking the link i sent?
I did, but I am a beginner so a lot of it is difficult for me to understand.
Oh wait, I see the beginner chat, I'll go there instead.
Didn't see that before, mb
prefabs cannot reference in-scene objects. you will have to pass the reference to the object when it is spawned by following the instructions in that link
dumb question: i got a namespace on some of my scripts, but not others. how do i get the namespace to reference my other scripts that do not have a namespace?
you don't have to do anything at all. they are in the global namespace so they can be referred to from any where
then the issue is not related to the namespace
it is
yep, that's a different assembly
the unity starter asset put a namespace on their code
and it makes it not able to reference anything
it has nothing to do with the namespace. that code is in a different assembly
you need to either remove the asmdef or give it a reference to the assembly your own code is in
asmdef?
yes, the assembly definition file that makes that puts that code into a separate assembly
okay, so how do i fix it?
that doesnt tell me what to do
i gave you two options for things to do. you need to do one of them
then i pick give it a reference. how do i do that?
do you use assembly definitions for your own code?
i have no idea what that is
yeah so the easiest option here is to simply remove the asmdef file
does that break the code at all? usually removing something is bad
how about you do some reading about what an assembly definition is
https://docs.unity3d.com/Manual/ScriptCompilationAssemblyDefinitionFiles.html
ahh, so this is why unity is so weird about reloading scripts
they need to remove this. maybe the editor will work better
did you even read the page i linked? because that says literally the opposite
i did and it says it causes the editor to only reload some files
yes, instead of recompiling every single script when you make a change to one, it only recompiles the code in that assembly. so by breaking your code up into separate assemblies, you make recompiling faster because you only recompile assemblies that have been changed (or had references changed)
Exactly, which make compile FASTER
But not everyone wants that
i dont care. im a solo indie dev that just wants my scripts to compile
but i guess i see the use in large groups
What could you possibly mean about this then?
#archived-code-general message
Because the default way unity works is how you seem to want it. There is nothing to remove
i removed the asmdef file to make the input system work
the other guy was actually really helpful, so thanks boxfriend
That's what I mean. By default there is no asmdef. So I'm confused about what unity should remove?
I just feel like I am missing something?
i think you are. im using the starter assets that unity gave out for their input system. it is under an assembly apparently, so i just deleted that and now it works perfectly.
Ah, they weren't in an asmdef when I used them, but that was a long time ago
ya, about a year ago i think, they combined the 1st person and 3rd person starter assets into 1. it's basically the same thing anyway. i just use it for their input script
it saves me time writing it out myself
they probably were, you just probably didn't try modifying the code to reference your own which was in a separate assembly
nah the assembly thing is part of the new one and not the old one
Gotcha, this was like 2017 or so. Or some long time ago
that would have been the standard assets then, starter assets are the replacements for that since it's been deprecated for a while
anyways, thanks boxfriend. you were helpful
Can you use gRPC with HTTP/2.0 when modding for Unity games? ๐
does anyone know of a way to fix the jittering when sliding off a slope ?
anyone know how to make github team planner look more like the trello format (like showing description under title without having to click on the task)
Not really a code question. Try #1157336089242112090 I guess? The mods may allow it there
I have an interface which has a Transform property.
{
public Transform Transform { get; }
}```
and I implement this on a MonoBehaviour:
```public class Detectable : MonoBehaviour, IDetectable
{
public Transform Transform => transform; // The exception will throw here.
}```
When I come to null check this I do:
// Target is of type IDetectable
if (Target.Transform == null) return; // When my target has been destroyed a MissingReferenceException exception is thrown above ^.
**How can I null check this?**
I'd rather not add a "IsTransformNull" bool to IDetectable. It would move the null check to implementers of the interface and not throw the exception, but that then has to be implemented every time and is not obvious to the team that the need to use **Target.IsTransformNull**
Is there another way?
In Detectable.cs:
public Transform Transform {
get {
return this == null ? null : transform;
}
}```
Legend!
alternatively something like this at the callsite:
if ((Target as UnityEngine.Object) != null && Target.Transform == null)```
That's awesome, thanks!
Is there a way to make this DRY? I've used some extension methods in places, but this is a property. I guess I could just make it a method, GetTransform() ๐ค
using System.Collections;
using System.Collections.Generic;
using System.Net;
using UnityEngine;
using UnityEngine.UIElements;
using static System.Runtime.CompilerServices.RuntimeHelpers;
public class playerJumping : MonoBehaviour
{
public Rigidbody2D rb;
public float speed;
private bool isGoingUpwards;
// Minimum vertical velocity thresold to consider movement. When we have this player is basically stationary in the middle
public float velocityThreshold = 0f;
public float verticalVelocity;
public float RDV; //Rotate Downwards Velocity
//public float RUV; //Rotate Upwards Velocity ( faster )
void Start()
{
rb = GetComponent<Rigidbody2D>();
Quaternion localRotation = gameObject.transform.localRotation;
// Access individual local rotation values (Euler Angles)
}
void Jump()
{
float verticalVelocity = rb.velocity.y;
RDV = verticalVelocity / 10;
//RUV = verticalVelocity / 5;
if (verticalVelocity > velocityThreshold)
{
isGoingUpwards = true;
}
if (verticalVelocity < velocityThreshold)
{
isGoingUpwards = false;
if (Input.GetKeyDown(KeyCode.Space) || Input.GetKeyDown(KeyCode.UpArrow) && (isGoingUpwards == false))
{
rb.AddForce(Vector2.up * speed, ForceMode2D.Impulse);
transform.Rotate(new Vector3(0, 0, -RDV));
}
transform.Rotate(new Vector3(0, 0, RDV));
}
}
// Update is called once per frame
void Update()
{
Jump();
}
}
dont crosspost..
Why the heck should it work?
ok
You're mixing up position and t
Rotation. Of course it wouldn't work.
if else
because without else your second rotate overrides the first
because it is executed each frame
So I'm not sure if this is a bug in my version of unity or if it's a code issue, but anyone know of a reason why trying to switch between one clip to another doesn't play the audio? the clip does swap in the audio source.
like this?
I just tried that and it still doesnt work
oh wait
somethings wrong about this I feel like
doesnt look right
if( !isGoingUpwards && (Space || UpArrow) )
hi, ive been trying for ages to get a sprite shape controller shaped in a triangle with sides A, B and C to have point B point towards an object relative to A.
but it jsut isnt working
im make a pastebin for the code
I've hit something and Visual Studio Mac went into this state, anyone knows how to unlock it? (beside force quit)
The rest of the editor works, just the code window is locked with that mini window overlayed
Does dragging it onto the tabs help?
Hi I have encountered problem in github.
I tried to switch branches in a github project where I chose to bring my changes to the new branches, then it got some confliction error with the new branch where it ask me to stash my changes, the stash features will mess up how the unity code sometimes, so I clicked not to stash the changes, and it makes my changes gone.
I'm not very familiar with github, is there possible for me to get my changes back?
Can I AddObjectToAsset before saving a root prefab?
hard to say exactly from your oexplanation but if you didn't commit the changes in your working directory to its own branch and also didnt stash them, and switched branches, then i think your changes might be gone.
basically... when you checkout a branch, that changes the contents of the working directly to match those of the branch
if there are changes in your working directory that were made since your last commit, those changes have to be saved somewhere or they will be lost when you checkout a different branch
you can either stash those changes, which stores them in a separate stash space, or you can directly commit those changes to some side branch
if you did neither then i think you might have lost those changes
git definitely has a learning curve...
This is perhaps a question regarding the Steam api, not sure. My game is about to exit EA. I want to give players a "founder's" item, that can only be found until the game's full release. After that players won't be able to obtain it. If a players uninstalls the game, but later decides to play it again, how would I know that they are eligible for the item?
I have not implemented cloud save, so that might be a solution.
You can get the time when the user purchased the app:
https://partner.steamgames.com/doc/api/ISteamApps#GetEarliestPurchaseUnixTime
Gets the time of purchase of the specified app in Unix epoch format (time since Jan 1st, 1970).
This is useful for rewarding users based on their initial purchase date.
Thank you, that looks like the ideal solution.
hi if anyone has a chance i could do with some help
some context- me and my friends are making a 3d top down stealth game i am currently working on a minigame similar to the wires task in amoungus, im struggling with the win condition i would like to remove my enemy ai and lasers from the scene for around 30 seconds then bring them back once the players has matched all wires.
the problem is im not sure how ive asked ai and searched for tutorials but cant find nothing that helps me any advice or help would be much appreciated
maybe instead of removing you should disable their scripts instead?
Think through your conditions. If you have pressed space this frame, or (if you have pressed up this frame while isGoindUpwards is false), you apply -RDV rotation for this frame.
If you did not press space this frame, or (you did not press up this frame while isGoingUpwards is true) you apply RDV rotation for this frame
These conditions are a mess and make no real sense. You can very easily satisfy both conditions, which would result in no rotation, and the first one will only ever apply one frame of rotation before the next one almost certainly undoes it
You should actually think through what conditions you want which one to happen under
would removing the script rid the obejcts from the scene? i need the ai and lasers to essiently become invisable and inactive
Send an event when you finish the task that makes these behaviors set a boolean and start a timer to un-set it. Then you just check if that boolean is false before you actually do anything
thankyou ill give it a whack
i knew the people from here would say that idek why i asked
because its nonsense to force old system to do what new system does out the box
I fixed it myself anyway so forget it
it should stop them from acting and diplaying. Check it out for yourself โ create primitive cube, disable the game object in the inspector โ it disappears and the scripts stop any Update()
you have a problem. there is a tool that solves that problem. You donโt want to use that tool. Thatโs your problem.
I fixed the problem just get over it
Nothing seems to help, I've googled a bit and it seems is a bug on vs mac... So nothing to do so far...
wow that is old af
VS for mac was in 2022 for a long time
its being retired though. Time to switch to VScode
Should probably change Type to Joystick Axis instead
Does resetting the Visual Studio in the Task Manager also not work?
Just gonna delete the messages cause people didn't read the parts where I said it's fixed
Thank you though
Hello everyone,
I've been encountering a persistent issue following the addition of Unity Ads alongside IronSource/LevelPlay in my Unity project. The specific errors that manifest after downloading and integrating Unity Ads are causing duplicate class conflicts related to AndroidX libraries. I have spent the past two days attempting to resolve these with manipulate gradle files but haven't yet found a suitable solution. Has anyone else faced a similar challenge, and if so, could you share how you addressed it? Any suggestions or guidance would be greatly appreciated.
internal InputAction[] kickInputs = null;
Hello, there is a subject I am curious about. When I open any array in visual studio, it is suggested to me to synchronise the variable with nulla. What does it do to synchronise the variable with nulla? Sample code above.
Yes, it's a bit strange ๐ Actually, the suggestion is just this. Instead of internal InputAction[] kickInputs; it suggests me to make internal InputAction[] kickInputs = null;
i guess if you're using it, without the assignment, it's unassigned, so it's saying you're using an unassigned variable...
usually you want to actually initialize the array though, not set it to null, but it depends on what your'e actually doing...
It's a field, so both versions do the same (it's initialized to null). Though I haven't seen this suggestion anywhere, so it must be a setting you enabled on your code editor
Sometimes suggestions are weird, sometimes it's just pointing out something you can do instead
In short, it's a completely useless suggestion, isn't it? It is already initialised as null.
Yes, you probably enabled a code style preference somewhere that forces you to explicit field initializations
Thank you for all the answers ๐ซก ๐ซก
Can somebody help me with NavMesh and making it better?
this is a code channel, ask a code question.. and read: https://dontasktoask.com/
I mean, I got it wokring wiht code
but alr
right so.. ask a specific question.. the URL explains why
okay, srr
hi, im trying to get the animated properties of an animation clip via script, is there any way to do that? pls ping me
Hello! Had a question regarding a system I want to build in my game. Basically, my game has different days that go by, and each day you have to survive waves of enemies. I want to build something that can track all the parameters of each day like:
- Length of day
- Number of Waves on day
- When the waves will change as a % of day length
- Spawn Rate of enemies for each wave (could be anywhere from 1 - 7 spawn rate values based on the number of waves that day)
- Number of events that will happen that day
- Which Events Will happen (These are prefabs that spawn a special event that would make the game harder, could be 1 - 4 events each day)
- What time each event will occur, how long the event will last, as well as any other event specific parameters (Have an event system built already, so I think I can tell that to separately change these based on the day)
- Drops that can spawn on day (These are also prefabs that spawn but are positive and help you progress)
I was thinking of using a lot of arrays so I can edit everything in the inspector, and load everything from those arrays based on the location in the array which would be connected to the day, so NumberOfWaves[7] would be the number of waves on Day 8. This does feel like its inoptimal though and would require a significant amount of arrays which might get messy.
Does anyone know a better way to do this? I just want it to be very modular and easy to edit for testing, as well as easy to add any additional parameters should I make changes to the game.
I am somewhat confused by your question, you're gonna have to store things in a collection no matter what. Whether that be a list, array, queue or whatever you want.
You can use scriptable objects so you can basically create an instance of a wave that can be dragged around in the inspector.
The only alternative to not storing them would be randomly choosing what a wave is at runtime, in which case you'll still be choosing randomly from a collection. Thus another array exists
Yeah, its less about whether I should use arrays I guess, and more about making sure the whole system doesn't get messy and overwhelming. I guess its less of an implimentation question and more of a clean code question. I would potentially have 100+ days with 10+ parameters for each day and it needs to be very easy for multiple people to come in, work on, swap out values easily, and keep track of everything.
Hey, when i use a script to load a new scene, it's lighting is all wrong (dark shadows). Anyonw knows what this can be caused by?
Assuming you need to manually assign values for each day, then scriptable objects will be nice here. Depending on your game, maybe you could generate these numbers at runtime based on some formula.
Though a formula will be harder to customize
#archived-lighting but I think this is just an editor issue. Should be there when you google the issue. I think it's fixed on later versions
I'd just make some type of timeline using a sorted queue and poll the first element then pop them off when it is to be executed.
oh, alright, thank you
does anyone know how i can solve this animation problem.
I'm trying to use lerp to start at "0" then go to "-100" then go to "+25" then return to "0". example in image attached.
Im also trying to use a while loop variable with time duration and an animation curve to acheive this.
is it possible? i'm also thinking about Lerp.Unclamped.. but my mind is stuck
animation curve is technically lerping
im tryiing to do something like this...
float duration = 0f;
while (duration < animationDuration)
{
duration += Time.deltaTime;
duration = Mathf.Clamp(duration, 0f, animationDuration);
float eval = animCurve.Evaluate(duration);
float value = Mathf.LerpUnclamped() <------------ stuck here
}```
is there a reason you cant use a defined curve
I don't think I will have to do much with formulas. It would all be custom, so I would manually set the values of all the parameters.
Example:
Day 4 Parameters
- Length: 180 seconds
- Waves: 3
- Wave 1 Change: 50% of length
- Wave 2 Change: 70% of length
- Wave 3 Change: 90% of length
- Wave 1 SpawnRate: 5/sec
- Wave 2 SpawnRate: 10/sec
- Wave 3 SpawnRate: 15/sec
- Number of Events: 2
- Event Prefabs: HoxBox, MeteorShower
- Event 1 Time: 33% of length
- Event 2 Time: 66% of length
- Drops: Drop1, Drop3, Drop5
Maybe I am overthinking it, and arrays for everything works. Just wanted to make sure I didn't build some giant complex system, realize it doesn't work great, and then have to rebuild it.
Plus some of it seems hard for arrays since a single day could have 3 waves with 3 different times, so I have to make an array for each wave. I could also make a jaggedarray where each day corresponds with an array that stores that days spawnrates, events, etc but then its not editable in the inspector
i could use a defined curve.. but i want to use the same animation curve for multiple effects at the same time to sycronize evertyhting.. so the animation curve will have a low value of -1 and a high value of +1 and convert based on that value specifically for an effect
not too sure what LerpUnclamped does here, but evaluating the animation curve with the time constraint usually all I need
you can also create animation curves at runtime, but for smooth curves you need to play around with weights which is a pain
right, its fine without it.
the idea with the unclamped is to set a min and max value for the curve and possibly multiply it?
for example. if the curve value is -1 it should equal -100. and the max value; +1, would be equal to +25. and a value of zero should equal zero
right, you can use them as multipliers which I do mostly too
pick a range, like -1 and 1 then normalize it to some values
ok so how do i set that up? so the animation will correctly match the animation curve image i have above
well, probably some math to define what values represent what at that value
but if i have values -1, 1 and i want to start at 0, and end at 0, then that means the duration should start at .5f? i don't understand how to achive this
I'd stick to 0 being 0, but if you want negative values then define a max of -1
such that for example -1 represents a value of -500, and 1 represents a max of 500
I do this because the UI for these things a little pain on the editor
that makes sence but what if i define -1 as -100 and +1 as 25? its oblonged so multiplication wont work espectially if 0 (the mid point) is still 0
well, then you need to define some type of algorithm with those values
You wouldnt need to store every single one of these into an array, I'm not sure where you would even want to apply the jagged array.
If you're doing this all in the inspector, you just have a array or list of Wave. The wave stores it's own array or list of whatever
Not sure what you mean exactly. If I have an array for the number of waves on a given day, how would that also have its own array of stored values? Wouldnt that be an array of arrays then? Or do you mean like a function that sets those values based on the value stored in the array?
Maybe I misunderstood what part you were asking about, but theres no need for any special handling of the arrays. What I am saying is that you shouldnt have an array of arrays specifically unless truly needed. It's just added confusion, what you really have is an array or list of data for the day. This will be some class. The class will then also have an array for example for the waves it has
Yes, by the end you can generalize it to being arrays within arrays but it's very different when it comes to readability. Also I dont think you can serialize array of arrays
Oh ok, that sounds pretty similar to how I started setting it up. I have a monobehavior called Days and its attached to my GameState Controller.
It tracks the currentDay, and loads all the parameters from the arrays for everything whenever the day changes, or the game is started
I guess that will work for now, and I see if it gets too overly complext. Apologies for the question, just wanted to make sure there wasn't a smarter way to do it before I go all in on setting it up.
Thanks for the help bawsi ๐
ok so for:
f(1) = 25
f(0) = 0
f(-1) = -100
since its quadratic such that ax^2 + bx + c
c = 0
a + b = 25
a - b = -100
so:
a = -37.5x^2
b = 62.5x
c = 0
f(x) = -37.5x^2 + 62.5x
I would really just use animation curve from 0 to 1 and remap the values
yeah honestly probably the better idea
anyway, you don't need to use lerp if you use an animation curve and evaluation every frame
because the curve itself is your source of linear interpolation
Physics.OverlapBox(detector.transform.position, Vector3.Scale(detector.size, detector.transform.lossyScale) / 2, detector.transform.rotation);
Is there a cleaner way of doing a manual box cast using an existing box collider?
there's collider.cast methods
Only in 2D.
oh yeah huh, wonder why
Collider2D.Cast is a wonderful method
i assume it is far more complex of an operation for Mesh colliders, which is why an analog does not exist for 3D
I was thinking just insert the colliders each fixed frame from OnTrigger and clear
basically what you do with nonalloc overlap anyway
Actually I think nonalloc doesn't clear but just inserts that amount of colliders which is why it returns a counter
Hi, I have a 2d mobile game where objects spawn within the screen boundaries, but need them to be interactable. Sometimes the objects spawn on the notch or outside the interactable zone. How do I get the interactable coordinates for a mobile device.
Thank you
How might you join 2 rigidbody objects into one without any parenting?
Joints
Is that absolutely necessary?
Because joints are not the behaviour I want. I have seen them disconnect and do all sorts of freaky shit.
I want more of a "weld", the objects just act as one
Could make the rigidbody update its position to follow the other one via code
Well that's what I do.
Well you have heard all three choices then
Parent, joint, follow code
There are no physics with following
that is literally what a joint does best
Well you have heard all three choices then
if you donโt want that, i do have another solution that I do for this. but you wonโt like it
like, you really wonโt like it
Tell me.
Write your own physics engine that has a separate feature to join objects together
Okay haha
Uh okay
Anyway I think I got it
@hard viper If I separate all of the colliders out under a phys object, I can move this back and forth to whatever I'm attaching
That works
But that's just parenting and defeats the purpose
I'll try to see if I can get around the parenting restriction
Guys how do you make tiles bigger in unity tilemaps
it's a bit complicated. at base, a tile is a scriptable object that you can i believe spawn as a menu item in your assets panel
you can configure all your tiles that way
then there's a tilemap pallette that you can add any number of tiles to
and then you can paint them in the editor or add them at runtime with specific tilemap methods
you can define specialized tiles by inheriting from tile or tilebase
you can also put a specific attribute on those tiles to add a menu item to add such tiles to your assets panel
I have configured all of the settings but i cant seem to find the one that changes the size
i'm pretty sure "size" would be part of the tilemap itself
all tiles, i believe, have the same size
your tilemap can have sizes with respect to world units
give me a sec i'll check it out for you...
Im booting up unity to check something
basic tiles have pretty much just a name and a sprite iirc
i should just keep a blank project open to answer these questions because unity takes forever to create a new project...
oh they expanded on this a lot since the version i used. it looks like the game mostly just assumes a 1:1 correspondence between tilemap tile size and world units, unless you specify a custom orientation, in which case you can adjust scale for example.
maybe i just never used their built in advanced tile types...
Then you want parenting
I don't understand why you're so against it TBH.
Also remove the Rigidbody from the child
I'm against it because it is a restriction of multiplayer.
What do you mean by that?
It is a restriction of multiplayer. I was told you can't do it.
ten billion line script copied from the internet
hey guys there's an issue with it
Theres no major issue, it's literally just the Player's Locomotion that I need help for?
But what does that mean? "Multiplayer"? You can have object hierarchies in multiplayer games, I have no idea what you mean by that.
In Fusion, there are networked properties. These are okay to modify any time and you can be sure that it will appear on everyone's client even if there's an issue with sending it when you change it.
Transform hierarchies, are not networked. You can get it right most of the time by setting the parent during an event everyone will recieve, but it is not guaranteed to be sent over network.
That's how I understand it. Now I am consulting them on how I might get around that limitation.
parenting objects with separate rigidbodies is super jank
the core issue is having separate rigidbodies
you can make an object with a rigidbody, and many child objects with colliders and no rigibody. Then all the child colliders get โcombinedโ in a way to the one rigidbody
that works. but if you try to give the children and parents both rigidbodies to move freely, but also coupled, you will have a big big problem
joints are like a constraint on physics simulation to basically say โif these two rigidbodies do not have this relationship of position/rotation relative to each other, apply this much force based on how wrong it is.โ with a force that is normally very large
itโs like a spring, basically. Apply force to X object based on how far it should be from a given relative position to Y object
Bruh all i needed to do was change "Pixels Per Unit" to 6
if you set the force to be massive, with infinite break force (ie it cannot break), then you are effectively โweldingโ two objects with a given relative positioning to each other