How to make bullet prefab take color of the character?
Okay, so I'm using a bullet prefab for the shooting. The bullet prefab is attached to my characters (both player and enemies), which shoot it out of their bodies. My characters get a random color for their body thanks to this script:
using UnityEngine;
using System.Collections;
public class ColorChanger : MonoBehaviour {
void Start() {
RandomColor();
}
public void RandomColor() {
GetComponent<SkinnedMeshRenderer>().material.color = new Color(Random.value, Random.value, Random.value);
}
}
I want the bullet prefab they shoot to have the same color as the characters that shoot it (if that's possible). So, pretty please, tell me if such a thing is possible and if so how could I do it. Please be specific because I'm a noob and if you have a simple script I could use, I would be eternally grateful.
Answer by ZefanS · Mar 14, 2016 at 03:00 AM
Well it looks like you're setting the colour of the player successfully, so doing so to the bullet will be by essentially the same process. The main thing is that you'll need to save the colour that you get when you set the player's. If you declare it as a variable then you will be able to assign it to the bullet later. First:
using UnityEngine;
using System.Collections;
public class ColorChanger : MonoBehaviour
{
public Color playerColor;
void Start()
{
RandomColor();
}
public void RandomColor()
{
playerColor = new Color(Random.value, Random.value, Random.value);
GetComponent<SkinnedMeshRenderer>().material.color = playerColor;
}
}
Then you'll have to do something along these lines:
//Somewhere in your shooting script...
void Shoot()
{
var bullet = GameObject.Instantiate(bulletPrefab, player.transform.location, Quaternion.identity);
bullet.GetComponent<SkinnedMeshRenderer>().material.color = playerColorFromTheColorChangerScript;
//And so on...
}
I'm going to assume you know how to access variables from other scripts, but if you need help with that just leave a comment.
Hope this helps!
@ZefanS First of all, I want to thank you so much for your help. I'm a total noob when it comes to scripting and pretty much everything else, so this helps a ton.
However, I'm a little confused by the second part. It's a long story but I wanted to make the projectiles instantiate inside the body of my player and enemies. But the problem I had is that my health and damage system registered every instantiation as damage.
To avoid that, I've made two projectiles with different tags, so that each delivers damage only to the other type of characters. I use a shooting script to make my player shoot and an enemy AI system for my enemies (which is a total mess right now and I'm stuck with that too).
Anyway, my shooting script is in Java script and is this: var projectile : Rigidbody; var speed = 10; var fireRate = 0.11; private var lastShot = -10.0;
function Update () {
if(Input.GetButtonDown("Fire1")){
if(Time.time > fireRate+lastShot){
clone = Instantiate(projectile, transform.position + new Vector3(0.0f, 1.7f, 0.0f), transform.rotation);
projectile.tag = "BulletTwo";
clone.velocity = transform.TransformDirection( Vector3 (0, 0, speed));
lastShot = Time.time;
}
Destroy(clone.gameObject, 3);
}
}
Being a total noob, I don't know how to access variables from other scripts or much of anything else. I know I have much to learn. So please, show me how you would adapt what you wrote for the shooting script into my code above, including the accessing variable part. And thank you sir! You are my hero!
No problem! Thanks for explaining the situation clearly and making an effort to learn.
$$anonymous$$odifying your shooting script is quite simple. We just need to add a public variable for the color and assign that color when we instantiate the bullet.
#pragma strict
//Here's the variable for the colour:
public var bulletColor : Color;
var projectile : Rigidbody;
var speed = 10;
var fireRate = 0.11;
private var lastShot = -10.0
function Update()
{
if(Input.GetButtonDown("Fire1"))
{
if(Time.time > fireRate+lastShot)
{
clone = Instantiate(projectile, transform.position + new Vector3(0.0f, 1.7f, 0.0f), transform.rotation);
projectile.tag = "BulletTwo"; //Shouldn't this be "clone.tag"?
//We assign the colour here:
clone.GetComponent.<Skinned$$anonymous$$eshRenderer>().material.color = bulletColor;
clone.velocity = transform.TransformDirection( Vector3 (0, 0, speed));
lastShot = Time.time;
}
Destroy(clone.gameObject, 3);
}
}
Here's the same script translated (with modifications) into C#:
using UnityEngine;
using System.Collections;
public class Shoot : $$anonymous$$onoBehaviour
{
public Color bulletColor;
public GameObject projectile;
public float speed = 20.0f;
public float fireRate = 0.11f;
private float lastShot = -10.0f;
private GameObject clone;
private Vector3 offset = new Vector3(0.0f, 1.7f, 0.0f);
void Update()
{
if(Input.GetButtonDown("Fire1"))
{
if(Time.time > fireRate+lastShot)
{
clone = Instantiate(projectile, transform.position + offset, transform.rotation) as GameObject;
projectile.tag = "BulletTwo"; //Shouldn't this be "clone.tag"?
//We assign the colour here:
clone.GetComponent<Skinned$$anonymous$$eshRenderer>().material.color = bulletColor;
//I don't really think you should do it like this... but okay.
clone.GetComponent<Rigidbody>().velocity = transform.TransformDirection(new Vector3(0.0f, 0.0f, speed));
lastShot = Time.time;
}
Destroy(clone.gameObject, 3);
}
}
}
The reason I translated this is because while it is possible to access things in a C# script from a JavaScript script and vice-versa, it's not straight forward. Generally, it's recommended that you pick a scripting language and stick to it for the entirety of the project if possible.
$$anonymous$$oving on, we'll need to add a reference to the shooting script in the script that picks the random colour. Doing so is pretty simple, but it really depends on where the two scripts are located. If they're both attached to the same game object then it's simpler. That seems like the most logical situation to me, so I'll write this example under that assumption, but you should have a look here to get a run down on all the various ways you can access a variable from another script. Here's the updated ColorChanger Script:
using UnityEngine;
using System.Collections;
public class ColorChanger : $$anonymous$$onoBehaviour
{
public Color playerColor = new Color(Random.value, Random.value, Random.value);
//Here's our variable that will hold a reference to the Shoot script
public Shoot shoot;
void Start()
{
RandomColor();
AssignColor();
}
public void RandomColor()
{
GetComponent<Skinned$$anonymous$$eshRenderer>().material.color = playerColor;
}
void AssignColor()
{
//Get a reference to the Shoot script
//Note that this assumes that ColorChanger and Shoot are attached to the same GameObject
shoot = GetComponent<Shoot>();
//Assign the player colour to the variable bulletColor in the Shoot script
shoot.bulletColor = playerColor;
}
}
@ZefanS I don't have enough words to thank you! I really appreciate your help and patience. The link you provided is very helpful and I have much to learn from it. Every day I'm striving to learn more and more.
I have attached both scripts to the same game object. I get no errors but when I hit play the game freezes and I get four error pause messages in the console. They are the same and repeat twice. They are as follows:
get_value can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Don't use this function in the constructor or field initializers, ins$$anonymous$$d move initialization code to the Awake or Start function.
ArgumentException: get_value can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Don't use this function in the constructor or field initializers, ins$$anonymous$$d move initialization code to the Awake or Start function.
ColorChanger..ctor ()
Could you please tell me what would be the best way to get around these errors. I've tried making some changes but nothing I've done is working. Again, thank you so much! You are a live saver!