Category Archives: Unity

Adding font to object

This was one of the questions I googled most over the span of several days.   Long story short, I wound up not adding font to an object, but adding objects to a 3D font (object).

Inserting text is hard, and it’s hard to make objects move around *with* the text in ways that make sense, particularly if you’ve done some crazy scaling shenanigans to make the text fuzzy like described in http://girlcodeitblog.com/2016/04/06/font-scale-and-transform-position/.

I wound up creating a 3D text object (under GameObject > 3D Object > 3D Text [all the way at the bottom]), doing said shenanigans, then utterly failing at adding a background color for the text.  This failure resulted in:

  • giving up and creating a 2D sprite of a blank white rectangle
  • dragging that in as a child object of my 3D text
  • scaling the child object to be the right size as background for the text
  • creating a material for the right color
  • dragging that onto the child object
  • futzing with directional lighting and material color emissions to make the color actually be what I want in the game context  (http://girlcodeitblog.com/2016/04/05/materials-can-be-annoying/)

This does not feel like the simplest way to achieve this, but it’s working for now.

(#todo go back and find some of the resources I used to answer it)

Font, scale, and transform.position interact in horrible ways

Did you know that:

1)  If you use the TextMesh component, with the font that comes with Unity (Arial – haven’t tried other fonts yet, google says that helps a little but doesn’t fix it), then making the font a normal size is super fuzzy and pixelated.  To get a clear image, I made my font sized 200, then scaled  down to like (.05, .05) (z appears unimportant in how my world is set up for scaling). *sources below

2)   So now I’ve got wonky scales on all my objects, some of them different depending on font size.

3)  A natural result of this is apparently that the transform positions across objects, even if they’re “the same”,  aren’t actually the same.  Placing objects automatically with Vector3 positions suddenly became much more unpleasant.  This is because “transform.position.y is determined in global space, transform.localScale is local.”  (from http://answers.unity3d.com/questions/186430/position-ascale-ratio.html – helpful tips in this one that feel hacky but seem necessary)

*http://forum.unity3d.com/threads/sharpenning-text.263810/ – some people give some other advice.  I want to check that out, and also check out if a Unity person has responded to this more recently than 2014.  This is a known problem, so maybe there’s a less CPU-eating fix than scaling up and scaling down constantly. #todo

 

 

Reset position of object

I’ve been lazy and resetting an object’s position to its start position manually with specific Vector3’s.  This gets annoying, though, because if I want to shift my layout, I also have to change multiple parts of my script.  It’d be way better if it did it automatically!

Super easy.  Make a new Vector3, it’ll get the position of the object that the script is attached to.

I had to make mine global so that multiple functions could access it.   I’m a little worried I’m making too many global variables, since I know that’s bad practice in general programming, but I’ll leave that to check out more later (#todo).

private Vector3 answerPosition; // make global variable 

Vector3 answerPosition = transform.position;  // get original location in Start()

answer.transform.position = answerPosition; // put this when you want it to move back to the original position 

The hacky thing is I have to put this in both of my scripts that are moving the object around.  There has to be a more concise way to do this, but I’ll figure that out next time round (#todo).

Gosh now it’s sending the object everywhere.  Hooboy.  Something’s gone very wrong!

Come to think of it, it’d be helpful to know how Debug.Log works. I’ll do that right now instead.  Okay. So click collapse on the console, and then click the speech bubble with the exclamation point in it – leftmost of the top right tabs in the console. (http://answers.unity3d.com/questions/757659/console-not-outputting-from-debuglog.html & http://answers.unity3d.com/questions/563309/i-cant-get-debuglog-to-work-at-all.html).

Debug.Log(answerPosition);

However, it’s only outputting this: UnityEngine.Debug:Log(Object) .

Oh now I feel silly!  There are two lines in each message (three if you click on it and look at the bottom).  The top line is the Vector3 I requested.  Got it.  Now I can see that my Vector3s are going all over the place, even just during the Start() function.  Let’s figure out what’s doing that …

There are apparently 4 different Vector3s that are happening here.  And Debug.Log() doesn’t seem to be working when I put it in again at the end of the coroutine.

Ah. Fixed it. Accidentally set it to “transform.position” instead of “answer.transform.position” when it was attached to a different game object, so it was sending it to random other game objects’ first locations.  Crazy!  Looks like I don’t need it to happen in both scripts, only the one attached to Answer.  And this also helped me realize that the other script shouldn’t be the one that makes Answer invisible in Start(), but instead to put that on the script attached to Answer.  Baby steps toward making this better! (At first this looked like it messed up my colliders, but after checking things, I restarted the program, and now it works.   ¯\_(ツ)_/¯  )

 

 

Materials can be annoying

I’m annoyed that when I want to change the color of an object, it actually changes the original material as well!  This isn’t parallel to how objects and prefabs work, where if you change an object away from its prefab, the program warns you, and then you can be like yes or no.  And once you’ve changed it, you can hit “apply” and change your prefab too, if you want!  Whereas materials just automatically changes your original material, and thus any other object that that material is a component of.  Grr.  (I’ve gotten better at remembering to duplicate materials, renaming, then making the renamed duplicate the component of the object whose material I want to change.)

Other fun thing I’ve been figuring out is what the heck “emission” means on materials, cuz it seems awfully important in getting my colors to look how I want them to.  #todo google lots about emission and actually understand it. (I’ve got it working for my purposes so I’m backburnering it.)

Relatedly, this morning I figured out that the reason one of my objects was a drastically different color than the other objects, despite having the same material (same emission, etc.), was because of the directional light’s direction.  Changed the rotation on the light and voila – they’re the same color (note that the position of the light doesn’t matter – it’s the rotation that changes how the light looks on the screen).  Took me like a week to figure out, which was frustrating, but makes sense given how new I am.  I’d watched this tutorial while falling asleep the other night (https://unity3d.com/learn/tutorials/projects/space-shooter/camera-and-lighting?playlist=17147), so that had helpfully primed me to even consider that my lighting could be doing things.  If you’re a beginner like me, I highly recommend watching the unity official tutorials (and others if you like them).  Even if those tutorials don’t look relevant, there’s probably something in there that’ll help you solve problems down the line.  Plus, it changes the pace nicely – sometimes I’m burned out on actively game-making, but it’s easy and even pleasant to watch someone else make a thing.

 

Resetting game state

In the game I’m making, every time a collision occurs, the game state resets to what it was originally – except without that object.  I realized that the problems in yesterday’s post on resetting the Answer object (http://girlcodeitblog.com/2016/04/04/resetting-answer-object-and-moving-it-back-in-progress/) was actually due to me relying on the Start() function to … start again?  For some reason?  It’s actually pretty cool, because I just had a conversation with E (my person, who happens to be a computer scientist) about the things I’ve been learning this week, and it tied in perfectly when I came back to fix my code this morning.  I used to use Python to do procedural things for linguistics research- take in a .csv file, do stuff to it in linear order, spit it back out again.  Same with R.  I never needed to think about functions on objects, just functions as easier ways of grouping together linear actions.  Because of this mental framework, I’d been unconsciously thinking of Start() as something that got looped back to after everything else ran.  Even though I knew consciously that wasn’t how it worked!

So I went through several different ways of resetting the game.  I tried to do it at the end of one of my object’s scripts, but for some reason that wasn’t working.  I tried putting Start() back into the function, which kind of worked, but not fully, because it was the wrong Start(). Oh wait – since all these objects exist at the beginning of the game, all of their Start()s happen at the same time.  Eesh this is confusing.  I’m going to go see if I can put the stuff I care about in the other script’s Start(), then recurse it, and see if that make this simpler than the other stuff I was trying.

Oh wait.  Silly to recurse Start().  Better just to make a function called PlaceAnswer() in the script I care about, and then call it.  I think the problem’s been that I’m not calling it after a “yield return new WaitforSeconds(#ofseconds)”.  Don’t fully understand coroutines yet, because the way I’m used to thinking is step-by-step python, so this is a fun brain stretch.  Okay yay it works!  That saves me some hassle and some bad hacks!

The other thing I was trying to do, that I didn’t keep in my final script, was access a function from a different script.  I got it to work this way :

(“PlayerCoroutine” is the name of the script, and that script has a function called PlaceAnswer() ) :

[used answers on http://answers.unity3d.com/questions/7555/how-do-i-call-a-function-in-another-gameobjects-sc.html]

At the top:

public PlayerCoroutine playercoroutine;

Later:

playercoroutine.PlaceAnswer();

So the reason this ended up not working for me permanently was that I actually delete objects throughout the game, and this required me putting an object with PlayerCoroutine attached to it into the public GUI slot for the script trying to reference it.  First of all, this felt annoying and hacky.  Second of all, that object gets deleted.  So I *could* put it on an object that doesn’t ever get deleted, but gosh that feels a ratsnest of code.

Resetting Answer object and moving it back – finished in “Resetting game state”

This post became too much of a hot mess, so I put the solution in “Resetting game state” at http://girlcodeitblog.com/2016/04/05/resetting-game-state/.   (#todo – why are urls not turning into links … )

But in the interest of saving my work, here’s my original thoughts on it:

I just moved an object onto a collider, everything else happened great, but it’s not moving itself back when I tell it to.

Tried this first:

transform.position = new Vector3(1.84f, 4.43f, 10f); // this is what I tried first and it didnt work

Why no worky?  Tried this.  Still no worky.

 gameObject.transform.position = new Vector3(1.84f, 4.43f, 10f);

So it turns out that the script on this object that allows it to be dragged and dropped by a mouse was the problem.  It was still moveable, and so it wouldn’t change its transform? Don’t quite understand.  But when I add this, suddenly it works:

            MoveObject otherScript = gameObject.GetComponent<MoveObject>();
//                MoveObject answerScript = GameObject.Find(Answer).AddComponent<MoveObject>();
            Destroy(otherScript);

 gameObject.transform.position = new Vector3(1.84f, 4.43f, 10f);

Now the trick is is make this object invisible again (it’s not supposed to be visible during gameplay, only as an answer), and add the MoveObject script back onto it so that when it becomes visible it can be dragged and dropped into the correct answer bin.

What I’d LIKE to do is deactivate it like this:

gameObject.SetActive(false);

However, when I do that, the rest of the game stops working, even when I set it back to active in the other script Start().  Sooo I’ll leave that for another day and just keep transforming the scale to Vector3(0,0,0).  Feels like a hack, but it sure works! (Got it from : http://answers.unity3d.com/questions/7776/how-to-make-an-gameobject-invisible-and-disappeare.html . Want to further explore the pros and cons of each option, but in the meantime I’m using some mix of this and SetActive(false), depending on which one works easily in context.)

gameObject.transform.localScale = new Vector3(0, 0, 0);

Now I just have to add my moveable script back onto the object after it’s been de-scaled.  Note – I tried to see if I could get away without deleting the script because I’d transformed the position and also the scale – turns out it puts it back in the spot I left it in?  Don’t know why.  Actually instead of messing with the MoveObject script, I’m going to see if setting the transform.position in the other script that calls it in its Start() function works.  Seems … cleaner somehow.

GameObject.Find(Answer).transform.position = new Vector3(1.84f, 4.43f, 10f); 

Gosh no that doesnt’ work at all.  Apparently I can’t descale that object while MoveObject script is on it.  Okedoke.  Someday I’ll understand why but in the meantime I’ll make it work.

Now I’ve got this:

 

            MoveObject otherScript = gameObject.GetComponent<MoveObject>();
////                MoveObject answerScript = GameObject.Find(“Answer”).AddComponent<MoveObject>();
            Destroy(otherScript);
//
            // move Answer back to original transform

            gameObject.transform.localScale = new Vector3(0, 0, 0);
            gameObject.transform.position = new Vector3(1.84f, 4.43f, 10f); // this is what I tried first and it didnt work
//            gameObject.SetActive(false);
            // destroyed audio sources  easy peasy 
//            MoveObject otherScript = AssetDatabase.LoadAssetAtPath(Assets/Scripts/MoveObject, typeof(MoveObject)); // apparently I don’t need this part because it’s already been defined, even tho it just got destroyed …
            otherScript = gameObject.AddComponent<MoveObject>();

Okay. So now the Answer object isn’t reappearing.  Messed sthing up somewhere.  It works for half of my objects but not the other half.  This doesn’t make much sense so I must’ve really done sthing fun in there.

I didn’t set it to the right z location, it was behind the background.

 

WRONG:

GameObject.Find(Answer).transform.localScale = new Vector3(0.08f, 0.08f, 0);

 

RIGHT:

GameObject.Find(Answer).transform.localScale = new Vector3(0.08f, 0.08f, 10);

And also apparently it’s not always picking up on the audio components of other objects.  It works for some, but not others.  I’m going to walk away from this soon and let everything marinate.  I think I’ll be able to solve it tomorrow.

Reset an object to the prefab state

I’ve got an object that gets filled up with new components during gameplay, particularly audio components.  Do I delete the one I just used and instantiate a prefab, or do I delete the audio components off of the object I’ve been using?  I tried both ways, and I’m sure there are ways to get both to work, but the one that worked better was deleting audio components off the object.  This is because that object was referenced in other scripts’ public variables through the GUI drag&drop stuff, and if I deleted that object outright, suddenly those scripts weren’t referencing the object anymore.

Here’s the script for getting all audiosources and destroying.  (Based on stuff from http://answers.unity3d.com/questions/275714/how-to-find-all-components-of-a-game-object.html)

            // destroyed audio sources  easy peasy 
            Component[] audioSources = gameObject.GetComponents<AudioSource>();
            foreach (Component audiosource in audioSources

{
                Destroy(audiosource);
            }

<— code block isn’t working there.  Probably don’t have my SmartSyntax set up right?  Gonna switch to GitHub Gist when I have the bandwidth. #todo

Here’s the script for instantiating the prefab (based on http://forum.unity3d.com/threads/editor-script-create-game-object-from-a-prefab.47845/).  Didn’t wind up keeping this one, but it’s nice to have on file.  Also I’ve had trouble loading assets at the path (before I’ve used Resources.Load, and am now wondering which one is better for my purposes – I’ll check that out in a later post! #todo).

            Object prefab = AssetDatabase.LoadAssetAtPath(Assets/Prefabs/Answer, typeof(GameObject));
            GameObject answer = Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject;