Unity 3d - Material Selection for Rendering - unity3d

I am trying to change the Material of wall at run time. I import the model of house from Google Sketchup, which has different materials all in one object (this is shown in the inspector). Whenever I click the next button (>>), it changes the first material of the object. How do I get the references to the other elements? This is what I have so far:
public class Material_GUI : MonoBehaviour {
public Material[] mats;
public GameObject go;
private int index = 0;
// Use this for initialization
void Start () {
go.renderer.material= mats[index];
}
// Update is called once per frame
void Update () {
}
void OnGUI(){
GUILayout.BeginArea(new Rect(Screen.width/2-100,Screen.height-60,200,50));
GUI.Box (new Rect(10,10,190,40),"");
GUI.Label(new Rect(62,20,100,20),"Wall Testing"+(index +1));
if(GUI.Button (new Rect(15,15,30,30),"<<")){
index--;
if(index<0){
index = mats.Length - 1;
}
go.renderer.material = mats[index];
}
if(GUI.Button (new Rect(165,15,30,30),">>")){
index++;
if(index > mats.Length -1){
index = 0;
}
go.renderer.material = mats[index];
}
GUILayout.EndArea();
}
}

If you want to change the other material of the renderer, you can use
go.renderer.materials
http://docs.unity3d.com/Documentation/ScriptReference/Renderer-materials.html?from=MeshRenderer
For example:
go.renderer.materials[0] = mats[0];
go.renderer.materials[1] = mats[1];

Related

I want to make it so when I click on the enemy, an ammo drop appears on the screen

Here is my code piece of code (I already have it so that when you click a ghost the ammo spawns, I just didn't include that because it was in a procedure.) My problem is with the RNG spawning of the ammo; it works fine at first and then after like 20 seconds it just does not spawn at all.
private void ammoSpawn()
{
ammoSpawner = rng.Next(1, 101);
if (ammoSpawner > 50)
{
ammoTimer.Activate();
if (ammoTimer.IsActive())
{
ammoRec.X = rng.Next(100, 1720);
ammoRec.Y = rng.Next(100, 700);
if (ammoTimer.IsFinished())
{
ammoRec.X = -100;
ammoRec.Y = -100;
ammoTimer.ResetTimer(true);
}
}
}
}
Any help is appreciated
I'm guessing that you're reusing the same ammo object, and that the variables such as ammoSpawner and ammoTimer are public variables in game1.
I would recommend creating a seperate class for the ammo object. So all related code can remain in the ammo object, and that also makes it easier to create multiple items. (In case you're going to expand on that in the future)
An example of a create method in the Ammo Class:
int spawner = 0;
int timer = 0;
Texture2D ammoSprite = new Texture2D;
Rectangle rec = new Rectangle(x, y, width, height);
public void Ammo(Texture2D ammoSprite, _spawner, _timer) //this should be the constructor that creates the class
{
spawner = _spawner;
timer = _timer;
rec.X = rng.Next(100, 1720);
rec.Y = rng.Next(100, 700);
}
public void Update()
{
//function where you put your update logic for the ammo object
}
public void Draw(Spritebatch spriteBatch)
{
//function where you put your draw logic for the ammo object
spriteBatch.Draw(ammoSprite, rect, Color.White);
}
then in the place where you'll use the ammo Class:
public Ammo ammo = null; //declared as a field on top of the page
private void ammoSpawn()
{
Ammo ammo = new Ammo(); //creating an Ammo object, should be inside
}
public void Update()
{
ammo.Update();
}
public void Draw()
{
SpriteBatch spriteBatch = new SpriteBatch();
ammo.Draw(spriteBatch);
}
Creating classes for objects are a core concept in C# to be able to reuse them. This also allows you to create multiple items/enemies that behave differently, but still keep the basic functions. I'd certainely recommend to learn about classes.

Character selection and uploading characters to the scene with photon pun2

I'm trying to develop a 3D multiplayer game with Unity. I don't know much about Photon, there are similar questions to the one I'm going to ask, but I still haven't found a solution. I will be glad if you help.
I have two scenes named "menu" and "game". In the menu scene, users make character selection after authenticating with playfab. After completing the selection, they connect to the lobby and set up a room and load the game scene. So far everything is successful. However, when the game scene is loaded, I have difficulty loading the characters selected by the users into the scene.
Here is the code file where I make the users choose their characters:
public class choose : MonoBehaviour {
private GameObject[] characterList;
private int index;
PhotonView PV;
private void Awake()
{
PV = GetComponent<PhotonView>();
}
private void Start()
{
index = PlayerPrefs.GetInt("CharacterSelected");
characterList = new GameObject[transform.childCount];
for (int i=0; i< transform.childCount; i++)
characterList[i] = transform.GetChild(i).gameObject;
foreach (GameObject go in characterList)
go.SetActive (false);
if (characterList [index])
characterList [index].SetActive (true);
}
public void ToggleLeft(){
characterList [index].SetActive (false);
index--;
if (index < 0)
index = characterList.Length - 1;
characterList [index].SetActive (true);
}
public void ToggleRight(){
characterList [index].SetActive (false);
index++;
if (index == characterList.Length)
index = 0;
characterList [index].SetActive (true);
}
public void kaydetbuton() {
PlayerPrefs.SetInt ("CharacterSelected", index);
} }
Here is the code file where I make the characters in the game move:
public class control : MonoBehaviour {
public FixedJoystick LeftJoystick;
private GameObject leftjoystick;
public FixedButton Button;
private GameObject button;
public FixedTouchField TouchField;
private GameObject touchField;
protected ThirdPersonUserControl Control;
protected float CameraAngle;
protected float CameraAngleSpeed = 0.2f;
PhotonView PV;
void Awake()
{
PV = GetComponent<PhotonView>();
}
void Start()
{
if (!PV.IsMine)
return;
Control = GetComponent<ThirdPersonUserControl>();
leftjoystick = GameObject.Find("Fixed Joystick");
if (leftjoystick != null)
{
LeftJoystick = leftjoystick.GetComponent<FixedJoystick>();
}
button = GameObject.Find("Handle (1)");
if (button != null)
{
Button = button.GetComponent<FixedButton>();
}
touchField = GameObject.Find("tfield");
if (touchField != null)
{
TouchField = touchField.GetComponent<FixedTouchField>();
}
}
void FixedUpdate() {
if (PV.IsMine)
{
Control.m_Jump = Button.Pressed;
Control.Hinput = LeftJoystick.Direction.x;
Control.Vinput = LeftJoystick.Direction.y;
CameraAngle += TouchField.TouchDist.x * CameraAngleSpeed;
Camera.main.transform.position = transform.position + Quaternion.AngleAxis(CameraAngle, Vector3.up) * new Vector3(1, 2, 3);
Camera.main.transform.rotation = Quaternion.LookRotation(transform.position + Vector3.up * 2f - Camera.main.transform.position, Vector3.up);
}
} }
There is a game object named "karakteryükle" in the menu scene. The code file named "choose" is in this object. There are 4 characters in this game object. Each character has a code file named "control", photon view, photon transform view, animator view component. And the game object named "karakteryükle" is also available as a prefab in the Resources folder.
I am sharing the picture of the components loaded on each character
I shared a picture of the game object named "karakter yükle"
I'm trying to load "karakter yükle" when the scene named game is loaded
PhotonNetwork.Instantiate("karakteryükle", new Vector3((float)-0.43, (float)1.1, (float)-25.84), Quaternion.identity, 0, null);
Result: The "karakteryükle" is loaded onto the stage, but the same character is loaded for each player, the character chosen by each player is not loaded.
I need your opinion on this.
Each player only knows their own setting for the index, because they use the value set in PlayerPrefs.
private void Start()
{
index = PlayerPrefs.GetInt("CharacterSelected");
}
This works for our local player, no problem there. But what happens when a different player enters the scene.
The playerObject is spawned on each client.
Each client handles that playerObject locally (this is the reason IsMine exist).
Player1 executes index = PlayerPrefs.GetInt(..) on their copy of Player2.
What you can do is send a buffered RPC to set the selected character on those remote copies. We want to buffer the rpc so new players change their remote copies of everyone to the appropriate character.
myPhotonView.RPC("SetCharacterIndex", RpcTarget.OthersBuffered, index);
and the corresponding RPC method
[PunRPC]
private void SetCharacterIndex(int index)
{
// Disable other characters and enable the one at this index
}
In the end you end up with something like
void Start()
{
characterList = new GameObject[transform.childCount];
for (int i=0; i< transform.childCount; i++)
{
characterList[i] = transform.GetChild(i).gameObject;
characterList[i].SetActive(false);
}
if (isMine)
{
index = PlayerPrefs.GetInt("CharacterSelected");
// Notify all remote copies of us to change their index
//
photonView.RPC("SetCharacterIndex", RpcTarget.OthersBuffered, index);
// Set the index locally
//
SetCharacterIndex(index);
}
}
[PunRPC]
private void SetCharacterIndex(int index)
{
if (characterList [index])
characterList [index].SetActive (true);
}
Hopefully that helps clear up the reason this happens (networking can be confusing at times).

Unity switching weapons on mobile

So, I have the following code for switching weapons inside a placeholder and I want to extend it, to switching weapons from a button too, so I will be able to switch them on my mobile too.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class WeaponSwitcher : MonoBehaviour {
public int selectedWeapon = 0;
// Use this for initialization
void Start () {
SelectWeapon();
}
// Update is called once per frame
void Update () {
int previousSelectedWeapon = selectedWeapon;
if (Input.GetAxis ("Mouse ScrollWheel") > 0f)
{
if (selectedWeapon >= transform.childCount - 1)
selectedWeapon = 0;
else
selectedWeapon++;
}
if (Input.GetAxis ("Mouse ScrollWheel") < 0f)
{
if (selectedWeapon <= 0)
selectedWeapon = transform.childCount - 1;
else
selectedWeapon--;
}
if (previousSelectedWeapon != selectedWeapon)
{
SelectWeapon ();
}
}
void SelectWeapon()
{
int i = 0;
foreach (Transform weapon in transform)
{
if (i == selectedWeapon)
weapon.gameObject.SetActive (true);
else
weapon.gameObject.SetActive (false);
i++;
}
}
}
What should I do? I'm newbie and everything I have tried didn't work :/
I have tried with an independent script just for the button to looking for which weapon is active and deactivate the other (there just two) etc but it didn't work.
public class ChangeWeapon : MonoBehaviour
{
public GameObject gun;
public GameObject shotgun;
void switchWeapons ()
{
gun = GameObject.Find("Gun");
shotgun = GameObject.Find("Shotgun");
if (gun.gameObject.activeSelf)
{
shotgun.gameObject.SetActive (true);
gun.gameObject.SetActive (false);
}
else
{
shotgun.gameObject.SetActive (false);
gun.gameObject.SetActive (true);
}
}
}
I found a really simple solution that works.
I placed two buttons on top of another, I disabled the second one and on click actions I do the followings:
Enable the second button
Disable the first button
Disable the first gun
Enable the second gun
And vise versa.
Image

Unity3d Sprite change with prefabs

Ive a question about how to change spirte images during runtime for a bunch of objects.
So i made a tiny racer 2d game, and therefore you can choose differend themes. You have this option in an integraded menu (not a seperate scene).
My question:
Can i switch the sprites easy during the runtime? Ive made prefabs for each track element - and i changed the sprites of those prefabs, but the change only gets visible, after the scene is reloaded. So i would need to avoid this.
Has someone a solution or a hint how i could do that?
Thanks in advance!
Code:
public class Background_Controller : MonoBehaviour {
public Camera mainCamera;
public Color colorNormal;
public GameObject[] Prefabs;
public Sprite[] normalSprites;
public Sprite[] tronSprites;
// Use this for initialization
void Awake () {
SwitchBackgroundFunction();
}
public void SwitchBackground(string Theme)
{
switch(Theme)
{
case "GreenHell":
PlayerPrefs.SetString("Theme", "Normal");
break;
case "NeonCity":
PlayerPrefs.SetString("Theme", "Tron");
break;
}
SwitchBackgroundFunction();
}
private void SwitchBackgroundFunction()
{
int prefabCount = Prefabs.Length;
if (PlayerPrefs.GetString("Theme") == "Normal")
{
mainCamera.backgroundColor = colorNormal;
for (int i = 0; i <= prefabCount - 1; i++)
{
Prefabs[i].GetComponent<SpriteRenderer>().sprite = normalSprites[i];
}
}
if (PlayerPrefs.GetString("Theme") == "Tron")
{
mainCamera.backgroundColor = Color.black;
for (int i = 0; i <= prefabCount - 1; i++)
{
Prefabs[i].GetComponent<SpriteRenderer>().sprite = tronSprites[i];
}
}
}
// Update is called once per frame
void Update () {
}
}
You can do something along the following lines to swap in a sprite from within your resources folder during runtime.
Sprite spr;
spr = Resources.Load<Sprite>("mysprite"); //insert name and file path to sprite within Resources folder
GetComponent<SpriteRenderer>().sprite = spr;

Unity2D: PlayerPrefs.HasKey

I'm using playerprefs to save data through out scenes. Although I'm having troubles with saving this data when the application is closed. You see I have a IAP shop that gives the player a boomerang when they purchase one, the boomerang effect (done inside my script) is activated through a button. My problem is, is that playerprefs.haskey isn't saving my boomerang effect when I close the game and then reopening it. Although it does save my boomerang effect when through scenes. This is my script:
public bool forceActive = false;
public GameObject BoomerangOn, BoomerangOff;
public static int buttonCount = 0;
static int timesActivated = 0;
void Start()
{
if (PlayerPrefs.HasKey ("boomerangbutton")) {
buttonCount = PlayerPrefs.GetInt ("boomerangbutton");
BoomerangEffect();
}
}
void Update()
{
PlayerPrefs.SetInt("boomerangbutton", buttonCount);
}
public void Activated ()
{
if(timesActivated < BoomeerangText.score)
{
timesActivated++;
StartCoroutine(BoomerangEffect());
}
}
IEnumerator BoomerangEffect()
{
BoomerangOn.SetActive (true);
yield return new WaitForSeconds (10.0f);
BoomerangOn.SetActive (false);
BoomerangOff.SetActive (true);
yield return new WaitForSeconds (1f);
BoomerangOff.SetActive (false);
forceActive = false;
}
Second Edit
Okay I research a bit and linked up boomerang effect script with my boomerang text script. When the user purchase a boomerang from my IAP store, they will get 5 boomerangs, once clicked on, the boomerang text int will go down (like 5, 4, 3, 2 and 1 ) and so will my buttoncount int(that is why the timesactivaed is needed). However I change the Activated function to:
public void Activated ()
{
if (timesActivated < BoomeerangText.score) {
timesActivated++;
StartCoroutine (BoomerangEffect ());
}
}
So far it works regarding activating my boomerang effect when the application is closed, but when it gets to the last int (1) nothing happens, my effect doesn't takes place, so far this is my only problem.
Above is an updated version of what my code looks like now. And below is my Boomerang text script:
public static int score = 0; // The player's score.
public static int click = 1;
public GameObject button;
Text text; // Reference to the Text component.
// Use this for initialization
void Start()
{
if (PlayerPrefs.HasKey ("boomerangTextInt")) {
score = PlayerPrefs.GetInt("boomerangTextInt");
}
}
void Awake()
{
text = GetComponent<Text>();
}
public void Update()
{
SetScoreText();
PlayerPrefs.SetInt("boomerangTextInt", score);
}
void SetScoreText()
{
text.text = " " + score;
if (score <= 0)
{
text.text = "None";
button.GetComponent<Button>().interactable = false;
}
else if (score >= 1)
{
button.GetComponent<Button>().interactable = true;
}
// Set the displayed text to be the word "Score" followed by the score value.
}
public void MinusBoomerangText()
{
score -= click;
text.text = " " + score;
}
}
And in my purchasing script I have this:
public int scoreValue = 5;
if (String.Equals(args.purchasedProduct.definition.id, PRODUCT_5_BOOMERANG, StringComparison.Ordinal))
{
BoomerangEffect.buttonCount += 5;
BoomerangText.score += scoreValue;
Debug.Log("Purchase successfull");
}
Thank you.:)
You are not calling .Save() which means all changes to PlayerPrefs are only in memory and are not persisted to disk, which means the next time you start the application all previous changes are lost.
Try the following in your save function.
void Update()
{
PlayerPrefs.SetInt("boomerangbutton", buttonCount);
PlayerPrefs.Save();
}
Disclaimer : I am not suggesting this is something you should do in your Update at all, as this in inefficient, but this is the root cause of your problem