- Home /
Switching between three characters while the others remain visible?
Hello, I'm sure this question has been asked before in some way, shape, or form, but I'm playing around with a game idea that has three separate characters that I wish to switch between, sort of like in Trine 2 except instead of disappearing upon the player control being disabled, I later hope to implement an AI script where they'll follow along with the character who's controlled by the player. The characters are three girls: Kat, Ozzie, and Shez. They all have separate behaviors (e.g., one girl exclusively can swim, another exclusively can jump very high, etc.), so it's important that they remain distinct. I'm playing around with the script from this video: http://www.youtube.com/watch?v=Xnyb2f6Qqzg. I added the "character switch" part of the script to the update function of that script. So far I only have Kat and Ozzie as sprites and gameobjects, but I've included Shez's "button". I used the key "O" to swich to Ozzie, "K" to switch to Kat, and "S" to switch to Shez. I modified the Update() function where I try to switch characters by enabling and disabling their respective "Controller" scripts.
using UnityEngine;
using System.Collections;
public class OzzieController : MonoBehaviour {
public float maxSpeed = 10f;
bool facingRight = true;
Animator anim;
bool grounded = false;
public Transform groundCheck;
float groundRadius = 0.2f;
public LayerMask whatIsGround;
public float jumpForce = 700f;
// Use this for initialization
void Start () {
anim = GetComponent<Animator>();
}
// Update is called once per frame
void FixedUpdate () {
grounded = Physics2D.OverlapCircle (groundCheck.position, groundRadius, whatIsGround);
anim.SetBool ("Ground", grounded);
anim.SetFloat("vSpeed", rigidbody2D.velocity.y);
float move = Input.GetAxis ("Horizontal");
anim.SetFloat ("Speed", Mathf.Abs (move ));
rigidbody2D.velocity = new Vector2 (move * maxSpeed, rigidbody2D.velocity.y);
if (move > 0 && !facingRight)
Flip ();
else if (move < 0 && facingRight)
Flip ();
}
void Update()
{
if(grounded && Input.GetKeyDown(KeyCode.Space))
{
anim.SetBool("Ground", false);
rigidbody2D.AddForce(new Vector2(0, jumpForce));
}
GetComponent<OzzieController>().enabled = true;
if(Input.GetKeyDown(KeyCode.K))
{
GetComponent<OzzieController>().enabled = false;
}
else if(Input.GetKeyDown(KeyCode.S))
{
GetComponent<OzzieController>().enabled = false;
}
else if(Input.GetKeyDown(KeyCode.O)){
GetComponent<OzzieController>().enabled = true;
}
else
GetComponent<OzzieController>().enabled = true;
}
void Flip()
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
Kat's code is identical except for the difference:
GetComponent<KatController>().enabled = false;
if(Input.GetKeyDown(KeyCode.K))
{
GetComponent<KatController>().enabled = true;
}
else if(Input.GetKeyDown(KeyCode.S))
{
GetComponent<KatController>().enabled = false;
}
else if(Input.GetKeyDown(KeyCode.O)){
GetComponent<KatController>().enabled = false;
}
else
GetComponent<KatController>().enabled = false;
}
Right now, when I play the game, Ozzie is automatically selected and active. I'm able to move her fine, while Kat stands still. I intend for her to be the default character selected so I'm happy with her selection state being defaulted to "true". When I press "O", which is her switch button, she's still selected. However, if I press "K" or "S", she's disabled. My problem is, pressing "K" doesn't seem to enable Kat. If I press "K", they both remain still and I can't control either of them, nor does pressing "O" again cause Ozzie to be enabled again.
Here's a screenshot of the animator:
There are no animations yet, as the sprites are still single images, but I took this from the tutorial in which it transitions from the idle to run animation if the speed parameter exceeds 0.01 and vise versa. Both game objects of Kat and Ozzie are on the "player" layer that I made, and each have an empty "groundCheck" game object as a child, also on the player layer. Everything /but/ the player layer is considered "ground" under the "whatIsGround" element. Basically, as the tutorial explained, if the character is on the ground (Ground = true), it plays the idle and run animations, but from any state they can jump or fall while ground = false (and it plays the jump animation).
I added this just in case it might be what's interfering with not being able to control them the way I want, rather than just bad scripting.
Thoughts on what I'm doing wrong?
P.S. I'm simply experimenting right now and I realize this is probably not the most efficient way to achieve switching characters by button-press, and I haven't even implemented the camera work yet. Of course I have this grandiose idea for a game that it's my dream to complete, but I'm trying to take little steps and just see what Unity can do first.
Answer by perchik · Mar 17, 2014 at 07:47 PM
A couple of suggestions.
First, consider creating a higher level script that just handles switching between the three characters. That way, each of the individual scripts only have information related to that character, and doesn't have to worry about links to other characters.
Then, I'd suggest to get the individual scripts once at start, instead of every frame on update, as getComponent tends to be slow (especially when called every frame.)
Something like this overall
public class charSwitcher:MonBehaviour{
public OzController oz;
public KatController kat;
public ShezController shez;
void Start(){
oz = GetComponent<OzController>();
//etc
}
void Update(){
if(input.getKeyUP( KeyCode.O) {
oz.enable;
shez.disable
kat.disable
}
}
}
Note, that's not really code and will not compile, but should at least give you the right idea
You don't have to answer this, but I implemented your code, and it seems to work just fine except for one thing! (I'm sure including Shez in there but not actually having her as a gameObject may have been an issue, but your idea is much more efficient nonetheless). When the game starts, they're both moving together rather than just Ozzie moving independently. When I hit "$$anonymous$$", $$anonymous$$at starts moving independently (which is what I wanted), but when I switch back to "O", they're moving together again. Is this due to $$anonymous$$at not being disabled originally? Here is the code:
public class charSwitcher : $$anonymous$$onoBehaviour {
public OzzieController oz;
public $$anonymous$$atController kat;
// Use this for initialization
void Start () {
oz = GetComponent<OzzieController> ();
kat = GetComponent<$$anonymous$$atController> ();
}
// Update is called once per frame
void Update () {
if(Input.Get$$anonymous$$eyUp($$anonymous$$eyCode.O)){
oz.enabled = true;
kat.enabled = false;
}
if(Input.Get$$anonymous$$eyUp ($$anonymous$$eyCode.$$anonymous$$)){
oz.enabled = false;
kat.enabled = true;
}
}
}
I tried adding "kat.enabled = false;" to the Start and Update functions independently, but it just disables $$anonymous$$at completely, and the button press doesn't enable her, which makes sense. I'll keep toying around to see if I can figure it out, but do you have any idea how I make it so that Ozzie moves independently? Note: I simply took the original code I wrote out of the "Controller" scripts so they have no character-switching elements anymore in the update function. Thanks for the help!
Also, it's generating a "NullReferenceException: Object reference not set to an instance of an object" error" on the lines "oz.enabled = true / kat.enabled = false" and "oz.enabled = false / kat.enabled = true" lines after I press "$$anonymous$$" and "O", if that helps.
Your answer
Follow this Question
Related Questions
Rigidbody causes ragdoll character to fly 4 Answers
Help with movement animation script 0 Answers
Smooth walljumping 0 Answers