I have a transparent texture of a chain link fence. I want the fence to fade in as the player approaches from the z direction. The problem I am having is that because the fence is transparent the opacity slider disappears and uses the image transparency. (I want the transparent texture to fade in) My current code:
public class WallFader : MonoBehaviour {
public GameObject wallone;
private Vector3 wallonetransform;
private Color wallonecolor;
public GameObject player;
private Vector3 playerposition;
private float PPX;
private float PPZ;
// Use this for initialization
void Start()
{
wallonetransform = wallone.GetComponent<Transform>().position;
wallonecolor = wallone.GetComponent<Renderer>().material.color;
}
// Update is called once per frame
void Update () {
playerposition = player.transform.position;
PPX = playerposition.x;
PPZ = playerposition.z;
// Distance to the large flat wall
float wallonedist = wallonetransform.z - PPZ;
if (wallonedist > 10)
{
wallonecolor.a = 0;
}
else
{
//fade in script
}
}
The fence never fades or disappears when wallonedist is > 10
Color is a struct which means that changing it won't change the instance of of the Renderer. It is a copy of a color from the Renderer. If you change the color, you have to re-assign the whole color back to the Renderer for it to take effect.
public class WallFader : MonoBehaviour
{
public GameObject wallone;
private Vector3 wallonetransform;
private Color wallonecolor;
Renderer renderer;
public GameObject player;
private Vector3 playerposition;
private float PPX;
private float PPZ;
// Use this for initialization
void Start()
{
wallonetransform = wallone.GetComponent<Transform>().position;
renderer = wallone.GetComponent<Renderer>();
wallonecolor = wallone.GetComponent<Renderer>().material.color;
}
// Update is called once per frame
void Update()
{
playerposition = player.transform.position;
PPX = playerposition.x;
PPZ = playerposition.z;
// Distance to the large flat wall
float wallonedist = wallonetransform.z - PPZ;
if (wallonedist > 10)
{
wallonecolor.a = 0;
renderer.material.color = wallonecolor; //Apply the color
}
else
{
//fade in script
}
}
}
Related
I am trying to make gameobject transparent using slider, but transparency could not work after writing the script. my shader setting is legacy standard/diffuse. so what changes should I make to this script? and also what setting I should make along with the script code. please help me out to work with the script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TransparentObject : MonoBehaviour
{
private GameObject objectTotransparent;
public float alpha = 0.3f;
//private float increaseAlpha;
//private float decreaseAlpha;
public Slider transparentSlider;
//renderer attached to the object that you want to make transparent
//public Renderer rend;
private Material currentMat;
/*void Awake()
{
transparentSlider.onValueChanged.AddListener(OnSliderChanged);
}*/
void Start()
{
//objectTotransparent = gameObject;
//currentMat = objectTotransparent.GetComponent<Renderer>().material;
AsistantControllScript = FindObjectOfType<AsistantControll>();
currentMat = currentGameObject.GetComponent<Renderer>().material;
}
void Update()
{
//ChangeAlpha(currentMat, alpha);
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
Ray ray = Camera.current.ScreenPointToRay(touch.position);
RaycastHit hitObject;
if (Physics.Raycast(ray, out hitObject))
{
objectTotransparent =
hitObject.transform.parent.transform.parent.gameObject;
objectTotransparent.GetComponent<Recolour>().SetSelected();
}
}
}
void ChangeAlpha(Material mat, float alphaVal)
{
Color oldColor = mat.color;
Color newColor = new Color(oldColor.r, oldColor.g, oldColor.b, alphaVal);
mat.SetColor("_Color", newColor);
}
public void ChangeAlphaOnValue(Slider slider)
{
ChangeAlpha(currentMat, slider.value);
}
public void Deselect()
{
objectTotransparent.GetComponent<Recolour>().SetOriginalMaterial();
objectTotransparent = null;
transparentSlider.value = alpha;
}
}
Change your material Rendering Mode into Transparent:
Why is this connecting all the health bars of my enemies together, even though their actual health is decreasing at its specified rate?
public class FillHealth : MonoBehaviour
{
Image HealthBar;
private NormalMonster normalMonster;
// Start is called before the first frame update
void Start()
{
HealthBar = GetComponent<Image>();
normalMonster = GameObject.FindGameObjectWithTag("Normal Monster").GetComponent<NormalMonster>();
}
// Update is called once per frame
void Update()
{
UpdateHealthLeft();
}
public void UpdateHealthLeft()
{
if (normalMonster.healthLeft > 0)
{
HealthBar.fillAmount = normalMonster.healthLeft / normalMonster.setHealth;
}
}
}
This is the script that is being referenced in FillHealth. As far as I understand it, since the variable isn't static, then the values should not be shared. It should find fill the health bar for each individual enemy.
public class NormalMonster : MonoBehaviour
{
private float _normalSpeed = 2f;
private float _BaseHealth = 20f;
private float _HealthModifier;
public float setHealth;
public float healthLeft;
// Start is called before the first frame update
void Start()
{
UpdateHealth();
}
// Update is called once per frame
void Update()
{
NormMonMov();
}
public void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Arrows")
{
healthLeft -= Arrows.Damage;
Destroy(other.gameObject);
if (healthLeft <= 0f)
{
Destroy(this.gameObject);
EarnedGold.earnedGold += 7;
Spawn_Manager.enemyCount--;
}
}
}
public void UpdateHealth()
{
if (StageMode.StageLvl > 5)
{
_HealthModifier = (StageMode.StageLvl * 0.01f) * _BaseHealth;
setHealth = Mathf.Round(_BaseHealth + _HealthModifier);
}
else
{
setHealth = _BaseHealth;
}
healthLeft = setHealth;
}
public void NormMonMov()
{
transform.Translate(Vector3.left * _normalSpeed * Time.deltaTime);
transform.position = new Vector3(Mathf.Clamp(transform.position.x, -7.0f, 10), transform.position.y, 0);
}
}
Any help would be greatly appreciated for this guy who just start playing with unity this weekend.
I believe the issue is with normalMonster = GameObject.FindGameObjectWithTag("Normal Monster").GetComponent<NormalMonster>();
If you have two Monsters
Both have two scripts attached, FillHealth and NormalMonster
Both the "FillHealth" scripts look for the FIRST gameobject in the scene that has a script with tag NormalMonster so both monsters are pointing to the exact same NormalMonster script (the first in the list)
Change "GameObject" capital G to "gameObject" lower case g
Still not the best way to code this, but that may work I think
Instead of getting the image, get the rect transform, like this
public RectTransform healthBar;
and change the length with:
healthBar.sizeDelta = new Vector2(normalMonster.healthLeft,healthBar.sizeDelta.y);
I'm working on a cars game and I'm trying to prevent the camera from moving horizontally if the model speed is null, I have tried many things, however I seem unable to do this because either when I get the camera to get locked it remains locked even if the object moves, and if not that it just keeps moving even with the object stopped, so I want to know how can I make that happen.
Code for cam Class
public class Cam : MonoBehaviour
{
public float sensitivityHor = 9.0f;
public float sensitivityVert = 9.0f;
public float minimumVert = -45.0f;
public float maximumVert = 45.0f;
public enum rotationAxes
{
//Given aliases to X and Y cordinates
keyX = 1,
}
public rotationAxes axes = rotationAxes.keyX;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Movement mov = GetComponent<Movement>();
if (mov.speed > mov.speed && mov.speed > 0 && axes == rotationAxes.keyX)
{
//Movimiento en el eje X de la camara
transform.Rotate(0, Input.GetAxis("Horizontal") * sensitivityHor, 0);
}
}
}
code for Movement class
public class Movement : MonoBehaviour
{
private CharacterController _charController;
public float speed = 3.0f;
// Start is called before the first frame update
void Start()
{
_charController = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
float deltaZ = Input.GetAxis("Vertical") * speed;
Vector3 movement = new Vector3(0, 0, deltaZ);
movement = Vector3.ClampMagnitude(movement, speed);
movement *= Time.deltaTime;
movement = transform.TransformDirection(movement);
_charController.Move(movement);
}
}
You never change the value of speed so what sense does it make to check it?
Rather store the actual speed you are going to apply to the object in this frame
public class Movement : MonoBehaviour
{
[Header("References")]
[SerializeField] private CharacterController _charController;
[Header("Settings")]
[SerializeField] private float speed = 3.0f;
[Header("Debug")]
[SerializeField] private float actualSpeed;
// public Read-only property
public float ActualSpeed => actualSpeed;
// Start is called before the first frame update
private void Awake()
{
if(!_charController) _charController = GetComponent<CharacterController>();
}
// Update is called once per frame
private void Update()
{
actualSpeed = Input.GetAxis("Vertical") * speed;
// It is cheaper to clamp a single float value then a vector
// since "GetAxis" retusn a value between -1 and 1
// it will anyway never be greater then "speed" so enough
// to clamp it downwards
actualSpeed = Mathf.Max(deltaZ, 0);
actualSpeed *= Time.deltaTime;
// This already uses the world space forward vector
_charController.Move(transfor.forward * actualSpeed);
}
}
And now you can rather check for this actualSpeed value
[RequireComponent(typeof(Movement))]
public class Cam : MonoBehaviour
{
[Header("References")]
// Better reference this already via the Inspector
[SerializeField] private Movement mov;
[Header("Settings")]
[SerializeField] private float sensitivityHor = 9.0f;
[SerializeField] private float sensitivityVert = 9.0f;
[SerializeField] private float minimumVert = -45.0f;
[SerializeField] private float maximumVert = 45.0f;
[Space]
[SerializeField] private rotationAxes axes = rotationAxes.keyX;
public enum rotationAxes
{
//Given aliases to X and Y cordinates
keyX = 1,
}
private void Awake()
{
// as fallback get it ONCE
if(!mov) mov = GetComponent<Movement>();
}
// Update is called once per frame
private void Update()
{
if (mov.ActualSpeed > 0 && axes == rotationAxes.keyX)
{
transform.Rotate(0, Input.GetAxis("Horizontal") * sensitivityHor, 0);
}
}
}
So I have 3 same images, but with different colors which I want to cycle in my menu. They are only with different hue/saturations and I want them to slowly reduce their alpha 1 by 1 so that the one behind pops up and then restart the cycle.
I'm trying to set a public image and reduce it's alpha, but it's not smooth.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class Fading : MonoBehaviour {
public Image image;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update ()
{
//image.CrossFadeAlpha(50, 5, false);
image.GetComponent<CanvasRenderer>().SetAlpha(0.1f);
image.CrossFadeAlpha(10f, 4f, false);
}
}
CrossFadeAlpha should only be called to start the image fade transition, via a button press or similar, as the method works similar to a Coroutine, example (on mouse button press);
public class ImageFade : MonoBehaviour
{
[SerializeField]
private Image m_img;
[SerializeField]
private float m_fadeDuration;
[SerializeField]
private bool m_ignoreTimeScale;
public void Update()
{
if (Input.GetMouseButtonDown(0))
m_img.CrossFadeAlpha(0f, m_fadeDuration, m_ignoreTimeScale);
if (Input.GetMouseButtonDown(1))
m_img.CrossFadeAlpha(1f, m_fadeDuration, m_ignoreTimeScale);
}
}
However if you would prefer to control this functionality manually, you have to take a longer approach. Below you can see that every time the mouse is pressed, the fade multiplier is negated, making it always 1 or -1. This value is then multiplied by the fraction of time needed for this update (before being added to the current alpha value);
Time.deltaTime / m_fadeDuration
As well as this, the boolean m_requiresUpdate, makes sure to avoid unnecessary updates, setting itself to false after the fade is complete.
public class ImageFade : MonoBehaviour
{
[SerializeField]
private Image m_img;
[SerializeField]
private float m_fadeDuration;
[SerializeField]
private bool m_ignoreTimeScale;
private int m_fadeMultiplier;
private float m_alpha;
private bool m_requiresUpdate;
public void Start()
{
m_fadeMultiplier = 1;
m_alpha = 1f;
}
public void Update()
{
//Toggle subtracting/adding
if (Input.GetMouseButtonDown(0))
{
m_fadeMultiplier = -m_fadeMultiplier;
m_requiresUpdate = true;
}
//Update
if (m_requiresUpdate)
{
//Fade
m_alpha = Mathf.Clamp(m_alpha + (m_fadeMultiplier * (Time.deltaTime / m_fadeDuration)), 0f, 1f);
m_img.canvasRenderer.SetAlpha(m_alpha);
//Finished fading
if (m_alpha == 0f || m_alpha == 1f)
m_requiresUpdate = false;
}
}
}
Hope this ties everything together nicely for you.
My project is a military fps and i'm having some problems with animations.
I have 3 different weapons, 1 animator controller for each one and every weapon has a "enter" and "leave" animation. Like CS, COD, etc...
I need to know when my "leave" animation ends to disable the gameobject, enable the other one and play the "enter" animation.
I tryed to do this: http://answers.unity3d.com/questions/362629/how-can-i-check-if-an-animation-is-being-played-or.html but without sucess.
I'll leave here a print of the animator controller, the hierarchy and the script, if u need more details, just need to say.
Animator controller of the weapon number 1
All transitions to "Sair" (leave animation) have a trigger (AK47_sair) and the transition to "Extit" state have a trigger ("AK47_SairControlador")
On my code, when i press 2 (change to weapon number 2) i want to do the transition.
This is the hierarchy, my script is attached to "Jogador".
With my actual code, it disable tha AK47 gameobject when the leave animation still playing.
using UnityEngine;
using System.Collections;
public class FirstPerson : MonoBehaviour {
public float speed;
public float normalSpeed = 5.0f;
public float slowSpeed = 2.5f;
public float crchSpeed = 2.5f;
private Transform tr;
private float dist; // distance to ground
public float mouseSensitivity = 5.0f;
public float verticalRotation = 0.0f;
public float updownRange = 60.0f;
private float verticalSpeed = 0.0f;
public float jumpSpeed = 5.0f;
CharacterController player;
private GameObject AK47;
private GameObject Faca;
public float shootingRate = 0.15f;
public float shootCooldown;
private bool agachado = false;
public float camOriginalPositionY;
public float camCrouchPositionY;
private Animator controladorAnimacaoAK;
private Animator controladorAnimacaoFaca;
public CapsuleCollider playerCollider;
public Camera CameraPrincipal;
public int ArmaSelecionada;
public int UltimaArma;
void Start () {
player = GetComponent<CharacterController>();
shootCooldown = 0;
controladorAnimacaoAK = player.GetComponentInChildren<Animator>();
playerCollider = gameObject.GetComponent<CapsuleCollider> ();
CameraPrincipal = Camera.main;
ArmaSelecionada = 1;
AK47 = CameraPrincipal.transform.FindChild ("ak47_final_animado").gameObject;
}
void Update () {
if (Input.GetKeyDown (KeyCode.Alpha2) || Input.GetKeyDown(KeyCode.Keypad2)) {
UltimaArma = ArmaSelecionada;
ArmaSelecionada = 2;
if(UltimaArma == 1) {
controladorAnimacaoAK.SetTrigger("AK47_Sair");
controladorAnimacaoAK.SetTrigger("AK47_SairControlador");
AK47.SetActive (false);
}
}
if (Input.GetKeyDown (KeyCode.Alpha1)) {
UltimaArma = ArmaSelecionada;
ArmaSelecionada = 1;
// controladorAnimacaoAK.SetTrigger ("AK47_Entrar");
}
if (ArmaSelecionada == 1) {
// diz ao controlador da anim se o player esta a movimentar-se ou nao
controladorAnimacaoAK.SetFloat ("AK47_Deslocacao", player.velocity.magnitude);
//Debug.Log (player.velocity.magnitude);
// dispatar tiros
PlayerShoot PlayerShootScript = player.GetComponent<PlayerShoot> ();
if (shootCooldown > 0) {
shootCooldown -= Time.deltaTime;
}
if (Input.GetButton ("Fire1")) {
if (shootCooldown <= 0) {
shootCooldown = shootingRate;
PlayerShootScript.FireShoot ();
// animaƧao
controladorAnimacaoAK.SetBool ("AK47_Disparar", true);
}
} else {
// animaƧao
controladorAnimacaoAK.SetBool ("AK47_Disparar", false);
}
if (Input.GetKeyDown (KeyCode.R)) {
controladorAnimacaoAK.SetTrigger ("AK47_rec");
}
}
}
}
In Unity 5 you've got this new thing which is Animation State Machine Behavior : State Machine Behaviours
You can use it to specify behavior when the Animation Controller enters or leave specific states.
For exemple here I've got my door which have an Open and Close state, and let's say that I want to play a sound when the door is opening.
Here I clicked Opening, then Add Behaviour and set a random name for the test (Behavior Test in my case)
Then I just need to implement the function void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) to play a sound at the first frame the animation is running.
[SerializeField]
AudioClip open_sound;
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
animator.GetComponent<AudioSource>().clip = open_sound;
animator.GetComponent<AudioSource>().Play();
}
In your case, you would want to implement a behavior in the state Disparar which implements the function OnStateExit([...]) and handle the weapon change.
To go a bit further I don't think you should handle the weapon change directly in the animation state, but maybe your script could send an event catched by a Game Controller that will actually handle the change of weapon.