I wanna make a system in my game where a ball that I have, will have a face on it which changes given what is found around it. So for example take this play through:
So the ball would probably be happy for a while until the last two explosions, where it’s just above spikes. I wanna detect what’s around the ball with Line Traces, though if you have a better idea, let me know.
Now, what I have issues with to start with, is that I want to have a dictionary of “faces” where the Key is an Enum for a face name, and the value is the Sprite that should be rendered on the ball. Faces like this:
But I can’t really find anything on how to do this, other than making a Prefab with an array of face sprites in it which doesn’t feel all that dynamic and easy to change. I’d be happier just having a component (FaceController.cs) that I can attach and then control it that way.
So what I thought I could do, would be to simply make Sprite Objects somewhere and then retrieve them at run-time so I can use them throughout the game. But this turned out to be harder than anticipated. I can’t seem to find anything that would suggest that you could create the 2DTextures a Sprite would need via Relative Paths to the raw PNG files and then create Sprites from that, which I could store in a Dictionary somewhere.
But I need something to assign to that sprite renderer…therein lies my issue. How do I make Sprite Objects that contain the 2D Texture that makes up what the SpriteRenderer should render?
You make them in the standard way, with the Sprite Editor. Why not?
It is possible to create Sprites dynamically from files, but I’m really not seeing why you would do that. Just create your sprites, add a Sprite[ ] array (or probably better, a bunch of explicitly named properties) to your script, and drag 'em in. I do this all the time, and have never felt like it was any big hardship.
Unless your game requires loading from files because they’re not available until runtime, or something like that?
Well I ended up making a “Resources” folder and then do this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace Assets.Data
{
public static class FaceSprites
{
public static Dictionary<FaceEnum, Sprite> Faces = new Dictionary<FaceEnum, Sprite>()
{
{FaceEnum.HAPPY, Resources.Load<Sprite>("Happy")},
{FaceEnum.SURPRISED, Resources.Load<Sprite>("Surprised")},
{FaceEnum.STRAINED, Resources.Load<Sprite>("Strained")},
{FaceEnum.UNFACED, Resources.Load<Sprite>("Unfaced")},
{FaceEnum.AMAZED, Resources.Load<Sprite>("Amazed")},
{FaceEnum.SUNGLASSES, Resources.Load<Sprite>("Sunglasses")},
{FaceEnum.TERRIFIED, Resources.Load<Sprite>("Terrified")}
};
}
}
Then I can do this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Assets.Data;
using System;
using System.Linq;
public class FaceController : MonoBehaviour
{
private SpriteRenderer spriteRender;
private Dictionary<FaceEnum, Sprite> faces;
private float waitTime = 0.2f;
public float timer;
private bool IsLevelPlaying;
// Use this for initialization
void Start()
{
faces = FaceSprites.Faces;
spriteRender = gameObject.AddComponent<SpriteRenderer>();
spriteRender.sprite = faces[FaceEnum.HAPPY];
IsLevelPlaying = true;
}
public void Update()
{
if (IsLevelPlaying == true)
{
timer += Time.deltaTime;
if (timer > waitTime)
{
RaycastHit2D[] hits = Physics2D.CircleCastAll(gameObject.transform.position, 1.75f, Vector2.zero, 10.0f);
//Vector2 start = new Vector2(gameObject.transform.position.x, gameObject.transform.position.y);
//DebugExtension.DebugCircle(start, Vector3.forward, Color.blue, 1.5f, 5.0f, false);
bool ForceHappyReaction = true;
hits = RemovePlayer(hits);
if (hits.Length > 0)
{
for (int i = 0; i < hits.Length; i++)
{
switch (hits[i].collider.tag)
{
case "Sun":
case "Spike":
spriteRender.sprite = faces[FaceEnum.STRAINED];
ForceHappyReaction = false;
i = hits.Length;
waitTime = 0.35f;
break;
case "Deadzone":
spriteRender.sprite = faces[FaceEnum.TERRIFIED];
ForceHappyReaction = false;
i = hits.Length;
waitTime = 0.35f;
break;
case "Cloud":
spriteRender.sprite = faces[FaceEnum.AMAZED];
ForceHappyReaction = false;
i = hits.Length;
waitTime = 0.35f;
break;
case "Sand":
spriteRender.sprite = faces[FaceEnum.UNFACED];
ForceHappyReaction = false;
i = hits.Length;
waitTime = 0.35f;
break;
case "Branch":
spriteRender.sprite = faces[FaceEnum.SURPRISED];
ForceHappyReaction = false;
i = hits.Length;
waitTime = 0.35f;
break;
}
}
}
else
{
ForceHappyReaction = true;
waitTime = 0.2f;
}
if (ForceHappyReaction == true)
{
spriteRender.sprite = faces[FaceEnum.HAPPY];
}
timer = 0f;
}
}
}
private RaycastHit2D[] RemovePlayer(RaycastHit2D[] array)
{
int index = -1;
for (int i = 0; i < array.Length; i++)
{
if (array[i].collider.tag == "Player")
{
index = i;
break;
}
}
if (index == -1)
{
return array;
}
else
{
List<RaycastHit2D> list = array.ToList();
list.RemoveAt(index);
array = list.ToArray();
return array;
}
}
void OnEnable()
{
GameStateController.AttachOnLevelStart(WhenLevelLoads);
GameStateController.AttachOnLevelPlay(WhenLevelPlays);
GameStateController.AttachOnLevelEnds(WhenLevelEnds);
}
void OnDisable()
{
GameStateController.DetachOnLevelStart(WhenLevelLoads);
GameStateController.DetachOnLevelPlay(WhenLevelPlays);
GameStateController.DetachOnLevelEnds(WhenLevelEnds);
}
void WhenLevelLoads()
{
}
void WhenLevelPlays()
{
IsLevelPlaying = true;
}
void WhenLevelEnds()
{
IsLevelPlaying = false;
spriteRender.sprite = faces[FaceEnum.SUNGLASSES];
}
}