I have a question I can't figure out myself for a long time. If I have a cube game object in Unity and I want to change it's color to red when I press the space key, all I have to do is write a script and write:
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
GameObject Cube = GameObject.FindWithTag("Cube");
Cube.GetComponent<Renderer>().material.color = Color.red;
}
}
But what if I want to change it's color to blue when I press the space key again?
For example, you can use a variable is_red and check its value in your update. Or maybe I didn't understand the problem
If you want to change the color on the second click you can simply add a If-statement that checks if the color is already equal to the wanted color and if it is change it to another color.
Example:
if (Input.GetKeyDown(KeyCode.Space)) {
// Get Cube GameObject
GameObject Cube = GameObject.FindWithTag("Cube");
// Get the Cube Renderer
Renderer rd = Cube.GetComponent<Renderer>();
// Is the color equal to red if it already is,
// change it to blue instead
if (rd.material.color = Color.red) {
rd.material.color = Color.blue;
}
else {
rd.material.color = Color.red;
}
}
Unrelated:
If the GameObject that has the Cube Tag stays the same GameObject over the game, I would advise you to rather "fetch" the GameObject and it's Renderer Component once at the start of the game instead of each time you press the space Key, to increase performance.
private GameObject cubeGO;
private Renderer cubeRD;
private void Start {
// Get Cube GameObject
cubeGO = GameObject.FindWithTag("Cube");
// Get the Cube Renderer
cubeRD = Cube.GetComponent<Renderer>();
}
You can now use these variables inise the Input.GetKeyDown(){}
if (Input.GetKeyDown(KeyCode.Space)) {
// Is the color equal to red if it already is,
// change it to blue instead
if (cubeRD.material.color = Color.red) {
cubeRD.material.color = Color.blue;
}
else {
cubeRD.material.color = Color.red;
}
}
Related
Following this question How to align sprites of smaller sizes to a moving gameobject sprite?, I'm trying to redraw my sprites to avoid rendering transparent pixels and try to maximize performance, and as I try starting this process with the sword sprites, I need to change the way the Sword game object follows the Player, which before was handled simply by using transform.position = hero.transform.position; because since both objects use sprites that are perfect squares they would have the same pivot point despite their size difference.
At first, it seemed to me the problem lied in how the pivots are different, thus I would need to update the transform position of the Sword every time its attack animation changes sprites. For that, I made a function which updates variables that influence the position as that gets updated:
here, heroTransform is a variable which gets sent the Player's transform property on the script's Start function as heroTransform = hero.transform;, where hero is defined right above it as hero = GameObject.Find("Hero");.
I would have expected this to make the Sword which is equipped with this script, called WieldablePosition to follow the player position, but it seems stuck in the same position as it starts:
I'm not sure, but I don't think I changed anything that would stop the Sword from moving. In what cases could a GameObject remain in a single place even as the transform.position is modified? For reference, please view the script:
using UnityEngine;
public class WieldablePosition : MonoBehaviour {
GameObject hero;
HeroMovement heroMovementScript;
private Transform heroTransform;
protected Animator anim;
private bool isAirAttackSingle;
private bool isFacingLeft;
private float x = 0;
private float y = 0;
void Start() {
hero = GameObject.Find("Hero");
heroTransform = hero.transform;
heroMovementScript = hero.GetComponent<HeroMovement>();
anim = GetComponent<Animator>();
isAirAttackSingle = heroMovementScript.isAirAttackSingle;
isFacingLeft = heroMovementScript.isFacingLeft;
}
void Update() {
UpdatePosition();
isAirAttackSingle = heroMovementScript.isAirAttackSingle;
isFacingLeft = heroMovementScript.isFacingLeft;
anim.SetBool("isAirAttackSingle", isAirAttackSingle);
if (isFacingLeft) {
transform.localScale = new Vector3(-1, 1, 1);
} else {
transform.localScale = Vector3.one;
}
}
public void SetPosition(AnimationEvent eventParams) {
string[] eventPositions = eventParams.stringParameter.Split(',');
x = float.Parse(eventPositions[0]);
y = float.Parse(eventPositions[1]);
}
private void UpdatePosition() {
transform.position = new Vector2(heroTransform.position.x + x, heroTransform.position.y + y);
}
}
Hello im new at AR development, i've tried to make a simple script that takes the camera position and the position of some object in the world and then draw a simple line between them using LineRenderer.
The object is tied to an imagetarget and im running with the FIRST_TARGET setting (so the world should have its origin (0,0,0) on the imagetarget)
However the camera position seems to be wrong for me and i dont really understand why. What i want is a line from the center of the mobile (Camera) screen to some object in the world viewed using an imagetarget. I would love some help with my issue. The code for my script is here:
public class POILine : MonoBehaviour
{
//Camera
private GameObject camera;
//Gameobject of interest to point the user towards
public GameObject to;
private GameObject toParent;
private LineRenderer line;
public float lineWidthMultiplier = 0.5f;
private float distance;
public float distanceMin = 50f;
void Start ()
{
camera = GameObject.FindGameObjectWithTag("MainCamera");
line = this.gameObject.AddComponent<LineRenderer>();
line.positionCount = 2;
//Thickness of the line
line.widthMultiplier = lineWidthMultiplier;
}
// Update is called once per frame
void Update ()
{
TrackableBehaviour.Status toStatus = to.transform.parent.GetComponent<TrackableBehaviour>().CurrentStatus;
if (toStatus == TrackableBehaviour.Status.TRACKED || toStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
{
distance = Vector3.Distance(camera.transform.position, to.transform.position);
if (distance > distanceMin)
{
line.enabled = true;
if (to != null)
{
//I think the error is here
line.SetPosition(0, camera.transform.position);
line.SetPosition(1, to.transform.position);
}
}
else
{
line.enabled = false;
}
}
}
Managed to get it working, what i did was that i placed an empty gameobject as a child to the Imagetarget i was currently tracking, then i made it follow the ARCamera transform position.
Then the code works by rendering a Line from that empty gameobject to the object of interest.
I have two players and these players are hitting a ball. Whenever they hit, there is a chance that ball's color may change.( green or red ). But when a player hit a ball it changes ball's color for only himself, other player's ball is the same color. I want all players to see the same color. Here is the code:
using UnityEngine;
using UnityEngine.Networking;
public class ColorGreen : NetworkBehaviour
{
// Use this for initialization
[SyncVar]
int temp = 0;
void Start () {
transform.GetComponent<Renderer>().material.color = Color.green;
}
// Update is called once per frame
void Update () {
if (!isServer)
return;
RpcCHANGE();
}
[ClientRpc]
void RpcCHANGE()
{
temp = Random.Range(0, 2);
if (temp == 0)
{
transform.GetComponent<Renderer>().material.color = Color.green;
}
else if(temp == 1)
{
transform.GetComponent<Renderer>().material.color = Color.red;
}
}
}
Ball Object has network identity checked "Local Player Authority". Can you guys tell me what I did wrong?
Thank you.
I think that when you call RpcCHANGE, it is called on each network instance, running the code within the method separately. This means that the result of Random.Range(0, 2); is different for each client.
Instead, you could generate the random color in the update method, and pass the color to RpcCHANGE, causing each network instance to be changed to the same color.
I have a small car game, and when I move up/down and left/right, the sprite becomes different. But the physicsbody remains the same. How do I adjust physicsbody? I added a screenshot of my sprite. At the moment I have Polygon physics body as on the right one.
Here is the code that adjusts animation states:
void FixedUpdate()
{
if (Input.GetKey(KeyCode.W)) {
rb2d.AddForce(Vector2.up * physicsConstant);
animator.CrossFade("CarUpIdle", 0);
} else if (Input.GetKey(KeyCode.S)) {
rb2d.AddForce(-Vector2.up * physicsConstant);
animator.CrossFade("CarDownIdle", 0);
} else if (Input.GetKey(KeyCode.D)) {
rb2d.AddForce(Vector2.right * physicsConstant);
animator.CrossFade("CarRightIdle", 0);
} else if (Input.GetKey(KeyCode.A)) {
rb2d.AddForce(-Vector2.right * physicsConstant);
animator.CrossFade("CarLeftIdle", 0);
}
}
To Change polygon based on sprite first you will need to have Serializefield variables to keep track of all the respective colliders. In this script basically what I do is I am keeping all the polygon colliders in array and iterate the array and enable it depending upon the sprite.
In the script im putting the required sprites along with the respective collider for sprite in sequence. So when I request the sprite to change I enable the respective collider and disables the other colliders. You will require something similer like this :
[SerializeField]
private Sprite[] Sprites;
[SerializeField]
private PolygonCollider2D[] Colliders;
private int index = 0;
private SpriteRenderer sp;
void Start () {
sp = GetComponent<SpriteRenderer>();
sp.sprite = Value[index];
}
void OnGUI() {
if(GUI.Button(new Rect(0,0, 80,35), "ChangeSprite")) {
colliders[index].enabled = false;
index ++;
if(index > Value.Length -1) {
index = 0;
}
sp.sprite = Sprites[index];
colliders[index].enabled = true;
}
}
Also in this tutorial it has been explained how to tackle this kind of problem
Unity Game Tutorial
Another way to proceed is to remove the ploygon collider and recreate it
Destroy(GetComponent<PolygonCollider2D>());
gameObject.AddComponent<PolygonCollider2D>();
though this is very bad programming considering I will be creating collider on every sprite change which is heavy on game.
I'm dealing with a problem for a few days now with setPixel() on Texture2D.
What i'm doing is getting mouse position or touch position(on android), then using that in setPixel() with transparent color. But the result i'm getting occur elsewhere instead of exactly where the mouse is...
public class EarshPic : MonoBehaviour {
public SpriteRenderer sr;
public SpriteRenderer srO;
public Camera c;
// Use this for initialization
void Start () {
CreateCover();//This method is working fine
}
private void CreateCover()
{
Color color = new Color(0.5F, 0.5f, 0.5F, 1.0F);
int x = srO.sprite.texture.width;
int y = srO.sprite.texture.height;
Texture2D tmpTexture = new Texture2D(srO.sprite.texture.width,
srO.sprite.texture.height);
for (int i = 0; i < tmpTexture.width; i++)
{
for (int j = 0; j < tmpTexture.height; j++)
{
tmpTexture.SetPixel(i, j, color);
}
}
tmpTexture.Apply(true);
sr.sprite = Sprite.Create(tmpTexture, srO.sprite.rect,
new Vector2(0.5f, 0.5f),srO.sprite.pixelsPerUnit);
}
// I have problem in that method
// Vector2 v = mousePostion or touchpostion
void Eraser(Vector2 v)
{
Color color = new Color(0.5F, 0.5f, 0.5F, 0.0F);
sr.sprite.texture.SetPixel(v.x, v.y, color);
sr.sprite.texture.Apply(true);
}
// Update is called once per frame
void Update () {
if(Input.mousePosition!=null)
{
Eraser(Input.mousePosition);
}
if (Input.touchCount == 1)
{
Touch touch = Input.GetTouch(0);
switch (touch.phase)
{
case TouchPhase.Moved:
Eraser(touch.position);
break;
}
}
}
}
Problem
You are mixing different coordinates. This is the case if the texture is not perfectly screen sized. Your click is in screen coordinates and you are using it to set the transparency in texture coordinates.
Solution
This one requires the use of 3D models with colliders and textures on them. For 2D scenario you can use a box and set its texture to your 2D sprite. I don't know any easier method, but hopefully there is.
You have to first convert the screen position to world coordinate ray. This can be done with Camera.ScreenPointToRay.
Then you need to Physics.Raycast that ray to chech which position of the 3d model's collider it is intersecting with.
The intersection point can be changed to texture coordinates with RaycastHit.textureCoord. In the previous link, you can find a complete code example of the whole process.