How can I change image fillamount direction? - c#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class loadingcolorful : MonoBehaviour
{
public float speed = 0.0f;
public bool fillAmount = false;
public bool rotate = false;
public bool changeRotationDir = false;
public bool changeFillDir = false;
private RectTransform rectTransform;
private Image imageComp;
// Use this for initialization
void Start()
{
imageComp = GetComponent<RectTransform>().GetComponent<Image>();
rectTransform = transform.parent.gameObject.transform.GetComponent<RectTransform>();
}
// Update is called once per frame
void Update()
{
if (fillAmount == true)
{
if (imageComp.fillAmount != 1f)
{
if (changeFillDir == true)
{
imageComp.fillAmount -= speed;
}
else
{
imageComp.fillAmount += speed;
}
}
else
{
imageComp.fillAmount = 0f;
}
}
else
{
if (imageComp.fillAmount == 0f)
{
imageComp.fillAmount = 0f;
}
else
{
imageComp.fillAmount = 1f;
}
}
if (rotate == true)
{
if (changeRotationDir == true)
{
rectTransform.Rotate(new Vector3(0, 0, -1));
}
else
{
rectTransform.Rotate(new Vector3(0, 0, 1));
}
}
}
}
The problem is at this place :
if (changeFillDir == true)
{
imageComp.fillAmount -= speed;
}
When it will get to 0 it will not continue to fill the image to the other direction just the image will stay empty. My guess is that the values of the FillAmount ragne is between 1 and 0.
Is there a way to make it happen ?

It's a bit of a hack, but you can switch to a negative scale value and start increasing the fillAmout again. This will make it fill in the other direction, taking the 0 point as pivot.
Assuming you are filling horizontally, flipping the scale would look something like this:
transform.localScale = new Vector3(-1, 1, 1);

A working solution like I wanted :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class loadingcolorful : MonoBehaviour
{
public float speed = 0.0f;
public bool fillAmount = false;
public bool rotate = false;
public bool changeRotationDir = false;
public bool changeFillDir = false;
public bool useBackGroundImage = true;
private RectTransform rectTransform;
private Image imageComp;
private Image backGroundImage;
// Use this for initialization
void Start()
{
imageComp = GetComponent<RectTransform>().GetComponent<Image>();
backGroundImage = transform.parent.gameObject.transform.GetComponent<Image>();
UseBackgImage();
}
// Update is called once per frame
void Update()
{
UseBackgImage(useBackGroundImage);
if (fillAmount == true)
{
if (imageComp.fillAmount != 1f)
{
if (changeFillDir == true)
{
if (imageComp.fillAmount == 0)
{
imageComp.fillAmount = 1f;
}
imageComp.fillAmount -= speed;
}
else
{
imageComp.fillAmount += speed;
}
}
else
{
imageComp.fillAmount = 0f;
}
}
else
{
if (imageComp.fillAmount == 0f)
{
imageComp.fillAmount = 0f;
}
else
{
imageComp.fillAmount = 1f;
}
}
if (rotate == true)
{
if (changeRotationDir == true)
{
rectTransform.Rotate(new Vector3(0, 0, -1));
}
else
{
rectTransform.Rotate(new Vector3(0, 0, 1));
}
}
}
private void UseBackgImage()
{
if (useBackGroundImage == true)
{
backGroundImage.enabled = true;
rectTransform = transform.parent.gameObject.transform.GetComponent<RectTransform>();
}
else
{
backGroundImage.enabled = false;
rectTransform = transform.GetComponent<RectTransform>();
}
}
private void UseBackgImage(bool UseBackGroundImage)
{
if (useBackGroundImage == true)
{
backGroundImage.enabled = true;
}
else
{
backGroundImage.enabled = false;
}
}
}

Related

Unity PUN 2 shooting not syncing

I wanted to add multiplayer to my game but i quickly faced many many problems, i cant find any clear solution online. i made a weapon script where the player can shoot and reload.
problems:
when i shoot, on 1 screen both players shoot, but at the other screen nothing happens
when i swap weapons, on 1 screen both players swap weapons, on the second screen nothing happens
note: im still a complete beginner so go easy on me please :)) thanks!
weapon script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using Photon.Pun;
public class weaponScript : MonoBehaviour
{
public weaponSO weaponStats;
public GameObject reloadingText;
public TMP_Text ammoValue;
public Transform firePoint;
public GameObject bulletPrefab;
public float bulletForce = 2f;
public bool isShooting;
public float pistolDamage;
public int currentAmmoClip = 1;
public int maxAmmoClip;
public int currentReserve = 1;
public int maxReserve;
public float reloadTime = 2f;
public bool isReloading = false;
public int bulletsShot;
public float startingDamage;
PhotonView view;
public void Start()
{
view = GetComponent<PhotonView>();
if(view.IsMine)
{
view.RPC("Update", RpcTarget.AllBuffered);
}
WeaponStats();
currentAmmoClip = maxAmmoClip;
currentReserve = maxReserve;
bulletsShot = maxAmmoClip - currentAmmoClip;
isShooting = false;
weaponStats.damage = startingDamage;
}
[PunRPC]
public void Update()
{
ammoValue.text = currentAmmoClip.ToString("0") + "/" + currentReserve.ToString("0");
if (Input.GetKeyDown(KeyCode.R))
{
if(currentReserve <= 0)
{
return;
}
if (currentAmmoClip == maxAmmoClip && !isReloading)
{
return;
}
else
{
StartCoroutine(Reload());
return;
}
}
if(Input.GetButtonDown("Fire1") && currentAmmoClip >= 1)
{
if(isReloading == false)
{
bulletsShot += 1;
currentAmmoClip -= 1;
isShooting = true;
Shoot();
FindObjectOfType<AudioManager>().Play("shot1");
return;
}
}
if(isReloading)
return;
if(currentAmmoClip <= 0 && currentReserve >= 1)
{
StartCoroutine(Reload());
return;
}
}
IEnumerator Reload()
{
reloadingText.SetActive(true);
isReloading = true;
yield return new WaitForSeconds(reloadTime);
if(currentReserve <= bulletsShot)
{
currentAmmoClip += currentReserve;
currentReserve = 0;
}
else
{
currentReserve -= bulletsShot;
currentAmmoClip = maxAmmoClip;
}
bulletsShot = 0;
reloadingText.SetActive(false);
isReloading = false;
}
void Shoot()
{
GameObject bullet = Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
Rigidbody2D rb = bullet.GetComponent<Rigidbody2D>();
rb.AddForce(firePoint.up * bulletForce, ForceMode2D.Impulse);
}
public void WeaponStats()
{
pistolDamage = weaponStats.initialDamage;
maxAmmoClip = weaponStats.maxAmmoClip;
maxReserve = weaponStats.maxReserve;
reloadTime = weaponStats.reloadTime;
bulletForce = weaponStats.bulletForce;
startingDamage = weaponStats.initialDamage;
}
}
weapon holder:
using UnityEngine;
public class WeaponHolder : MonoBehaviour
{
public int selectedWeapon = 0;
void Start()
{
SelectWeapon();
}
void Update()
{
if(FindObjectsOfType<weaponScript>()[0].isReloading == true)
{
return;
}
else
{
switchWeapon();
}
}
public void switchWeapon()
{
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();
}
}
public void SelectWeapon()
{
int i = 0;
foreach (Transform weapon in transform)
{
if(i == selectedWeapon)
{
weapon.gameObject.SetActive(true);
}
else
{
weapon.gameObject.SetActive(false);
}
i++;
}
}
}
i tried adding
if(view.IsMine == true)
{
Debug.Log("true");
}
else
{
Debug.Log("false");
}
but nothing happened and i couldnt shoot anymore. thanks for reading
The problem is you don't sync anything in your game. This means the other computer can't know what it has to do.
Whenever you want to sync something you have to call an RPC function.
Maybe watch some tutorials about how to do this properly and how to set up a simple multiplayer lobby.
EDIT:
What the other comments above mentioned with .IsMine is true, but you're doing it wrong. You have to call this in start or awake and whenever the view is not yours you disable the camera of the person only and disable shooting. Its important to only do this on your computer! If you are not doing everyone will shoot when you press Shoot and everyone will walk when you walk.

How do I know when the fading coroutine is over when fading out or in?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fading : MonoBehaviour
{
[Header("Fading")]
public List<GameObject> objectsToFade = new List<GameObject>();
public float duration;
public Coroutine fadeCoroutine;
public bool automatic = false;
public bool startFading = false;
[Header("Random")]
public bool randomObjects = false;
public bool randomDuration = false;
public bool faded = false;
private bool fadeInOut = false;
private bool coroutineIsRunning = false;
private List<Material> objectsToFadeMaterials = new List<Material>();
private bool randomOnce = false;
private Material randomMaterial;
private float originalDuration;
private void Start()
{
originalDuration = duration;
for (int i = 0; i < objectsToFade.Count; i++)
{
objectsToFadeMaterials.Add(objectsToFade[i].GetComponent<Renderer>().material);
}
}
private void Update()
{
if (startFading)
{
if (automatic)
{
if (!coroutineIsRunning)
{
Fade();
}
}
else
{
if (Input.GetKeyDown(KeyCode.G))
{
Fade();
}
}
}
}
private void Fade()
{
fadeInOut = !fadeInOut;
if (fadeCoroutine != null)
StopCoroutine(fadeCoroutine);
if(randomDuration)
{
duration = Random.Range(1, 20);
}
else
{
duration = originalDuration;
}
if (randomObjects && objectsToFade.Count > 1)
{
if (randomOnce == false)
{
randomMaterial = objectsToFadeMaterials[Random.Range(0, objectsToFadeMaterials.Count)];
randomOnce = true;
}
if (fadeInOut)
{
fadeCoroutine = StartCoroutine(FadeTo(randomMaterial, 0, duration));
}
else
{
fadeCoroutine = StartCoroutine(FadeTo(randomMaterial, 1, duration));
}
}
else
{
for (int i = 0; i < objectsToFadeMaterials.Count; i++)
{
if (fadeInOut)
{
fadeCoroutine = StartCoroutine(FadeTo(objectsToFadeMaterials[i], 0, duration));
}
else
{
fadeCoroutine = StartCoroutine(FadeTo(objectsToFadeMaterials[i], 1, duration));
}
}
}
}
public IEnumerator FadeTo(Material material, float targetOpacity, float duration)
{
Color color = material.color;
float startOpacity = color.a;
float t = 0;
coroutineIsRunning = true;
while (t < duration)
{
t += Time.deltaTime;
float blend = Mathf.Clamp01(t / duration);
color.a = Mathf.Lerp(startOpacity, targetOpacity, blend);
material.color = color;
if(t > duration)
{
coroutineIsRunning = false;
}
if(color.a == 1)
{
randomOnce = false;
}
if(color.a == 0)
{
faded = true;
}
yield return null;
}
}
}
I know that if the color.a is 0 then the object faded out finished then I set faded to true.
In the second script that is attached to a teleporter I want to start teleporting if the object faded out then teleport to the next teleporter and fade in back and so on.
This script is attached to each teleporter :
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class Teleport : MonoBehaviour
{
public Fading fading;
public List<GameObject> objectsToTeleport = new List<GameObject>();
//Start is called before the first frame update
void Start()
{
objectsToTeleport = GameObject.FindGameObjectsWithTag("ObjectToTeleport").ToList();
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter(Collider other)
{
StartCoroutine(fading.FadeTo(objectsToTeleport[0].GetComponent<Renderer>().material, 0, 2));
}
}
and this script is the teleporting script :
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net.WebSockets;
using UnityEngine;
using UnityEngine.Scripting.APIUpdating;
public class Teleporting : MonoBehaviour
{
public List<ObjectToTeleport> objectsToTeleport;
public List<ObjectToTeleport> currentlyTeleportedObjects;
public List<GameObject> teleporters;
public float teleportingTime;
public float teleportingStartTime;
public bool startTeleporting = false;
public GameObject[] groups;
public bool loop = false;
public bool random = false;
public int teleportationsCount = 0;
[Serializable]
public class ObjectToTeleport
{
public GameObject teleportableObject;
public int teleportOrder;
}
public void Start()
{
StartTeleporting();
}
private void Update()
{
}
public void StartTeleporting()
{
if (startTeleporting)
{
if (teleporters.Count > 1 && objectsToTeleport.Count > 0)
{
InvokeRepeating("MoveTeleportableObjects", teleportingStartTime, teleportingTime);
}
}
}
private void MoveTeleportableObjects()
{
if (teleportationsCount < objectsToTeleport.Count)
currentlyTeleportedObjects.Add(objectsToTeleport[teleportationsCount]);
for (int i = 0; i < currentlyTeleportedObjects.Count; i++)
{
if (!loop)
{
MoveObjects(i);
}
else
{
MoveObjects(i);
}
}
teleportationsCount++;
}
private void MoveObjects(int i)
{
GameObject destinationTeleporter = teleporters[currentlyTeleportedObjects[i].teleportOrder];
currentlyTeleportedObjects[i].teleportableObject.transform.position = destinationTeleporter.transform.position;
if (currentlyTeleportedObjects[i].teleportOrder < teleporters.Count - 1)
{
currentlyTeleportedObjects[i].teleportOrder++;
}
else if (loop == true)
{
{
currentlyTeleportedObjects[i].teleportOrder = 0;
}
}
}
}
I need somehow a synchronization between the fading and the teleporting in the Teleport script.
But it seems a bit complicated.
The Fading script on it's own and the Teleporting script on it's own are working fine but making a synchronization between them is the problem.
Update :
What I tried :
In the Fading script I added two methods FadIn and FadeOut and calling the FadeOut in the Teleport script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fading : MonoBehaviour
{
[Header("Fading")]
public List<GameObject> objectsToFade = new List<GameObject>();
public float duration;
public Coroutine fadeCoroutine;
public bool automatic = false;
public bool startFading = false;
[Header("Random")]
public bool randomObjects = false;
public bool randomDuration = false;
public bool faded = false;
private bool fadeInOut = false;
private bool coroutineIsRunning = false;
private List<Material> objectsToFadeMaterials = new List<Material>();
private bool randomOnce = false;
private Material randomMaterial;
private float originalDuration;
private void Start()
{
originalDuration = duration;
for (int i = 0; i < objectsToFade.Count; i++)
{
objectsToFadeMaterials.Add(objectsToFade[i].GetComponent<Renderer>().material);
}
}
private void Update()
{
if (startFading)
{
if (automatic)
{
if (!coroutineIsRunning)
{
Fade();
}
}
else
{
if (Input.GetKeyDown(KeyCode.G))
{
Fade();
}
}
}
}
private void Fade()
{
fadeInOut = !fadeInOut;
if (fadeCoroutine != null)
StopCoroutine(fadeCoroutine);
if(randomDuration)
{
duration = Random.Range(1, 20);
}
else
{
duration = originalDuration;
}
if (randomObjects && objectsToFade.Count > 1)
{
if (randomOnce == false)
{
randomMaterial = objectsToFadeMaterials[Random.Range(0, objectsToFadeMaterials.Count)];
randomOnce = true;
}
if (fadeInOut)
{
fadeCoroutine = StartCoroutine(FadeTo(randomMaterial, 0, duration));
}
else
{
fadeCoroutine = StartCoroutine(FadeTo(randomMaterial, 1, duration));
}
}
else
{
for (int i = 0; i < objectsToFadeMaterials.Count; i++)
{
if (fadeInOut)
{
fadeCoroutine = StartCoroutine(FadeTo(objectsToFadeMaterials[i], 0, duration));
}
else
{
fadeCoroutine = StartCoroutine(FadeTo(objectsToFadeMaterials[i], 1, duration));
}
}
}
}
private IEnumerator FadeTo(Material material, float targetOpacity, float duration)
{
Color color = material.color;
float startOpacity = color.a;
float t = 0;
coroutineIsRunning = true;
while (t < duration)
{
t += Time.deltaTime;
float blend = Mathf.Clamp01(t / duration);
color.a = Mathf.Lerp(startOpacity, targetOpacity, blend);
material.color = color;
if(t > duration)
{
coroutineIsRunning = false;
}
if(color.a == 1)
{
randomOnce = false;
}
yield return null;
}
}
public IEnumerator FadeIn(Material material, float duration)
{
StartCoroutine(FadeTo(material, 1, duration));
yield return new WaitForSeconds(duration);
}
public IEnumerator FadeOut(Material material, float duration)
{
StartCoroutine(FadeTo(material, 0, duration));
yield return new WaitForSeconds(duration);
}
}
In the Teleport script
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class Teleport : MonoBehaviour
{
public Fading fading;
public List<GameObject> objectsToTeleport = new List<GameObject>();
//Start is called before the first frame update
void Start()
{
objectsToTeleport = GameObject.FindGameObjectsWithTag("ObjectToTeleport").ToList();
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter(Collider other)
{
StartCoroutine(fading.FadeOut(objectsToTeleport[0].GetComponent<Renderer>().material, 3));
}
private void OnTriggerExit(Collider other)
{
}
}
How do I continue from here ? what should I do next ?
There are multiple ways.
Simply yield the routine
You already have both as Coroutines so you could wrap them in another Coroutine and yield return it instead of StartCoroutine (this is something you should do in FadeIn and FadeOut anyway!)
// If this returns IEnumerator Unity automatically runs it as Coroutine
private IEnumerator OnTriggerEnter(Collider other)
{
yield return fading.FadeOut(objectsToTeleport[0].GetComponent<Renderer>().material, 3));
// Something after fading finished
Debug.Log("Fade Out finished!");
}
You could of course as well have them separately like
private void OnTriggerEnter(Collider other)
{
StartCorouine (EnterRoutine(other));
}
private IEnumerator EnterRoutine ()
{
yield return fading.FadeOut(objectsToTeleport[0].GetComponent<Renderer>().material, 3));
// Something after fading finished
Debug.Log("Fade Out finished!");
}
Callback
Another way would be passing in a callback that is executed once the routine finishes like e.g.
private void OnTriggerEnter(Collider other)
{
StartCoroutine(fading.FadeOut(objectsToTeleport[0].GetComponent<Renderer>().material, 3, OnFadeOutFinished));
}
private void OnFadeOutFinished ()
{
Debug.Log("Fade Out finished!", this);
}
or using a lambda, especially helpful if you want to do something with the other reference
private void OnTriggerEnter(Collider other)
{
StartCoroutine(fading.FadeOut(objectsToTeleport[0].GetComponent<Renderer>().material, 3, () => {
Debug.Log("Fade Out finished!");
}));
}
and have it as parameter in your routine like
private IEnumerator FadeTo(Material material, float targetOpacity, float duration, Action callback)
{
Color color = material.color;
float startOpacity = color.a;
float t = 0;
coroutineIsRunning = true;
while (t < duration)
{
t += Time.deltaTime;
float blend = Mathf.Clamp01(t / duration);
color.a = Mathf.Lerp(startOpacity, targetOpacity, blend);
material.color = color;
if(t > duration)
{
coroutineIsRunning = false;
}
if(color.a == 1)
{
randomOnce = false;
}
yield return null;
}
callback?.Invoke();
}
public IEnumerator FadeIn(Material material, float duration, Action callback = null)
{
yield return FadeTo(material, 1, duration, callback));
}
public IEnumerator FadeOut(Material material, float duration, Action callback = null)
{
yield return FadeTo(material, 0, duration, callback));
}
There are a lot of ways you could do this, but I personally in this case would create new coroutines FadeIn and FadeOut, instead of directly calling the following:
fadeCoroutine = StartCoroutine(FadeTo(objectsToFadeMaterials[i], 0, duration));
Then, at the end of your FadeOut coroutine you can take some additional step(s) to trigger a teleport or whatever else you need to trigger. It looks like you don't want your Fading to hold a reference to your Teleporting, which is smart, so you could choose to fire an event instead that your Teleporting component can subscribe to.

Bullet doens't move. Unity

I am working on a 2D, topdown, roguelike game but i got stuck when i tried to make a shooting system.
when i run it and press the arrow keys, the bullet spawns and points in the right direction. It juste doesn't move in any way.
This is my code and i hope someone can figure it out. Btw, everything is connected. The player and the bullet prefab.
using System.Collections;
using System.Linq;
using UnityEngine;
namespace Assets.Scripts
{
[RequireComponent(typeof(Player))]
public class PlayerShootController : ShootControllerBase
{
[SerializeField]
private int _numberOfBombs;
public int NumberofBombs
{
get { return _numberOfBombs; }
set { _numberOfBombs = value; }
}
[SerializeField]
private PlayerHeadController _headObject;
public PlayerHeadController HeadObject
{
get { return _headObject; }
set { _headObject = value; }
}
[SerializeField]
private Bomb _bombPrefab;
public Bomb BombPrefab
{
get { return _bombPrefab; }
set { _bombPrefab = value; }
}
public bool IsShooting { get; private set; }
private KeyCode _shootKey;
private Vector2 _shootDirection;
private Player _player;
public override void Start()
{
base.Start();
_player = GetComponent<Player>();
}
public override void Update()
{
base.Update();
if (IsShooting)
{
SetHeadDirection(_shootKey);
return;
}
if (InputHelpers.IsAnyKey(KeyCode.UpArrow, KeyCode.DownArrow, KeyCode.LeftArrow, KeyCode.RightArrow))
{
if (Input.GetKey(KeyCode.UpArrow))
{
_shootDirection = new Vector2(0, BulletSpeed);
_shootKey = KeyCode.UpArrow;
}
else if (Input.GetKey(KeyCode.DownArrow))
{
_shootDirection = new Vector2(0, -BulletSpeed);
_shootKey = KeyCode.DownArrow;
}
else if (Input.GetKey(KeyCode.LeftArrow))
{
_shootDirection = new Vector2(-BulletSpeed, 0);
_shootKey = KeyCode.LeftArrow;
}
else if (Input.GetKey(KeyCode.RightArrow))
{
_shootDirection = new Vector2(BulletSpeed, 0);
_shootKey = KeyCode.RightArrow;
}
StartCoroutine(Shoot());
}
if (NumberofBombs > 0 && InputHelpers.IsAnyKeyDown(KeyCode.LeftShift, KeyCode.RightShift, KeyCode.E))
{
var bomb = (Bomb) Instantiate(BombPrefab);
bomb.transform.position = transform.position;
NumberofBombs--;
}
}
IEnumerator Shoot()
{
IsShooting = true;
while (Input.GetKey(_shootKey))
{
var bullet = (Rigidbody2D)Instantiate(BulletPrefab);
bullet.GetComponent<BulletScript>().Shooter = transform.gameObject;
bullet.transform.position = transform.position;
if (_shootDirection.y > 0)
{
bullet.transform.Rotate(0, 0, -90);
}
else if (_shootDirection.y < 0)
{
bullet.transform.Rotate(0, 0, 90);
}
else if (_shootDirection.x > 0)
{
TransformHelpers.FlipX(bullet.gameObject);
}
bullet.AddForce(_shootDirection);
bullet.AddForce(_player.GetComponent<Rigidbody2D>().GetPointVelocity(_player.transform.position) * 0.02f);
if (ShootClips.Any())
{
var clipToPlay = ShootClips[Random.Range(0, ShootClips.Count)];
clipToPlay.pitch = Random.Range(MinShootPitch, MaxShootPitch);
clipToPlay.Play();
}
yield return new WaitForSeconds(ShootingSpeed);
}
IsShooting = false;
//Reset head flipping
if (_headObject.transform.localScale.x < 0)
{
TransformHelpers.FlipX(_headObject.gameObject);
}
}
private void SetHeadDirection(KeyCode shootKey)
{
switch (shootKey)
{
case KeyCode.UpArrow:
_headObject.SetHeadDirection(PlayerHeadController.HeadDirection.Up);
break;
case KeyCode.DownArrow:
_headObject.SetHeadDirection(PlayerHeadController.HeadDirection.Down);
break;
case KeyCode.LeftArrow:
_headObject.SetHeadDirection(PlayerHeadController.HeadDirection.Left);
break;
case KeyCode.RightArrow:
_headObject.SetHeadDirection(PlayerHeadController.HeadDirection.Right);
break;
}
}
}
}
try this:
bullet.AddForce(_shootDirection*moveSpeed*Time.deltaTime);
instead of this:
bullet.AddForce(_shootDirection);
bullet.AddForce(_player.GetComponent<Rigidbody2D>().GetPointVelocity(_player.transform.position) * 0.02f);
tweak the speed for desired result, and if you want the bullet to follow the player you will need to update the shoot direction every certain time with a couroutine

Problems making anim.SetBool work with NavMeshAgent

I am working on setting up a simple little AI for a character in my game. For some reason I am having major problems getting animations to play while using the NavMeshAgent and I do not understand why. This is a waypoint system that I pooled off Unity API, and I can't even seem to get this working. I am hoping that if someone can give me some input on this if might clear some other things up as well. I am really lost here and would appreciate any input. The code on the bottom all works until it hits Patrol and then the player moves without animating. I feel like there is something more i need to know about navmesh's maybe. Or a lot more I need to know about programming in general.
e// Patrol.cs
using UnityEngine;
using UnityEngine.AI;
using System.Collections;
public class Enemy_Patrol : MonoBehaviour
{
public Transform[] points;
public Animator anim;
private int destPoint = 0;
private NavMeshAgent agent;
void Start()
{
agent = GetComponent<NavMeshAgent>();
anim = GetComponent<Animator>();
// Disabling auto-braking allows for continuous movement
// between points (ie, the agent doesn't slow down as it
// approaches a destination point).
agent.autoBraking = false;
GotoNextPoint();
}
void GotoNextPoint()
{
// Returns if no points have been set up
if (points.Length == 0)
return;
// Set the agent to go to the currently selected destination.
agent.destination = points[destPoint].position;
anim.SetBool("WalkForwards", true);
anim.SetBool("IsIdle", false);
// Choose the next point in the array as the destination,
// cycling to the start if necessary.
destPoint = (destPoint + 1) % points.Length;
}
void Update()
{
// Choose the next destination point when the agent gets
// close to the current one.
if (!agent.pathPending && agent.remainingDistance < 0.5f)
GotoNextPoint();
}
}
// Code i wrote to handle following chasing etc.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class AI_Tester : MonoBehaviour
{
private float patrolSpeed = .2f;
public NavMeshAgent agent;
public GameObject[] waypoints;
private int waypointInd = 0;
public Transform player;
static Animator anim;
public SealForce_DestructableObjects destructableObjects;
public Transform enemy;
// Use this for initialization
void Start()
{
anim = GetComponentInChildren<Animator>();
agent = GetComponent<NavMeshAgent>();
destructableObjects = GetComponent<SealForce_DestructableObjects>();
waypoints = GameObject.FindGameObjectsWithTag("waypoints");
waypointInd = Random.Range(0, waypoints.Length);
}
void AIMovements()
{
if (Vector3.Distance(player.position, this.transform.position) <= 30)
{
Vector3 direction = player.position - this.transform.position;
direction.y = 0;
this.transform.rotation = Quaternion.Slerp(this.transform.rotation,
Quaternion.LookRotation(direction), 0.1f);
if (direction.magnitude > 15)
{
MoveToFiringRange();
}
if (direction.magnitude <= 15)
{
AttackPlayer();
}
}
else if (Vector3.Distance(player.position, this.transform.position) > 30)
{
WaitingOnAction();
}
}
public void Update()
{
AIMovements();
}
public void AttackPlayer()
{
anim.SetTrigger("IsAttacking");
anim.SetBool("IsIdle", false);
anim.SetBool("RunForwards", false);
}
public void MoveToFiringRange()
{
this.transform.Translate(0, 0, 0.04f);
anim.SetBool("RunForwards", true);
anim.SetBool("IsIdle", false);
anim.ResetTrigger("IsAttacking");
}
public void WaitingOnAction()
{
anim.SetBool("IsIdle", true);
anim.SetBool("RunForwards", false);
StartCoroutine("BackToPatrol");
}
//program works fine all the up to here. The only thing wrong with patrol is no animation.
IEnumerator BackToPatrol()
{
yield return new WaitForSeconds(5);
anim.SetBool("IsIdle", false);
Patrol();
}
public void Patrol()
{
Debug.Log("In Patrol");
agent.speed = patrolSpeed;
if (Vector3.Distance(this.transform.position, waypoints[waypointInd].transform.position) >= 2)
{
agent.SetDestination(waypoints[waypointInd].transform.position);
anim.SetBool("WalkForwards", true);
}
if (Vector3.Distance(this.transform.position, waypoints[waypointInd].transform.position) <= 2)
{
waypointInd += 1;
if (waypointInd > waypoints.Length)
{
waypointInd = 0;
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class AI_Tester : MonoBehaviour
{
public bool isPatrolling;
private float patrolSpeed = 1.5f;
public NavMeshAgent agent;
public GameObject[] waypoints;
private int waypointInd = 0;
public Transform player;
static Animator anim;
//public SealForce_DestructableObjects destructableObjects;
//public Transform enemy;
// Use this for initialization
void Start()
{
anim = GetComponentInChildren<Animator>();
agent = GetComponent<NavMeshAgent>();
//destructableObjects = GetComponent<SealForce_DestructableObjects>();
waypoints = GameObject.FindGameObjectsWithTag("waypoints");
waypointInd = Random.Range(0, waypoints.Length);
}
void AIMovements()
{
if (Vector3.Distance(player.position, this.transform.position) <= 30)
{
Vector3 direction = player.position - this.transform.position;
direction.y = 0;
this.transform.rotation = Quaternion.Slerp(this.transform.rotation,
Quaternion.LookRotation(direction), 0.1f);
if (direction.magnitude > 15)
{
//StopCoroutine("BackToPatrol");
StopCoroutine("Patrol");
isPatrolling = false;
MoveToFiringRange();
}
if (direction.magnitude <= 15)
{
//StopCoroutine("BackToPatrol");
StopCoroutine("Patrol");
isPatrolling = false;
AttackPlayer();
}
}
else if (Vector3.Distance(player.position, this.transform.position) > 30 && !isPatrolling)
{
//StopCoroutine("BackToPatrol");
StopCoroutine("Patrol");
WaitingOnAction();
}
}
public void Update()
{
AIMovements();
}
public void AttackPlayer()
{
anim.SetTrigger("IsAttacking");
anim.SetBool("IsIdle", false);
anim.SetBool("RunForwards", false);
}
public void MoveToFiringRange()
{
this.transform.Translate(0, 0, 0.04f);
anim.SetBool("RunForwards", true);
anim.SetBool("IsIdle", false);
anim.ResetTrigger("IsAttacking");
}
public void WaitingOnAction()
{
anim.SetBool("IsIdle", true);
anim.SetBool("RunForwards", false);
StartCoroutine("BackToPatrol");
}
IEnumerator BackToPatrol()
{
isPatrolling = true;
yield return new WaitForSeconds(5);
anim.SetBool("IsIdle", false);
yield return StartCoroutine ("Patrol");
isPatrolling = false;
}
IEnumerator Patrol()
{
Debug.Log("In Patrol");
agent.speed = patrolSpeed;
agent.SetDestination(waypoints[waypointInd].transform.position);
anim.SetBool("WalkForwards", true);
while (Vector3.Distance(this.transform.position, waypoints[waypointInd].transform.position) >= 2 && !isPatrolling)
{
yield return null;
}
waypointInd++;
if (waypointInd >= waypoints.Length) waypointInd = 0;
}
/* public void Patrol()
{
Debug.Log("In Patrol");
agent.speed = patrolSpeed;
if (Vector3.Distance(this.transform.position, waypoints[waypointInd].transform.position) >= 2)
{
agent.SetDestination(waypoints[waypointInd].transform.position);
anim.SetBool("IsIdle", false);
anim.SetBool("WalkForwards", false);
}
if (Vector3.Distance(this.transform.position, waypoints[waypointInd].transform.position) <= 2)
{
waypointInd += 1;
if (waypointInd > waypoints.Length)
{
waypointInd = 0;*/
}
You are calling WaitingOnAction on Update every frame, which will set the animator's IsIdle back to true and start a new BackToPatrol coroutine. This should not happen. Try to check if the character has reached it's destination before calling WaitingOnAction again. Something like:
else if (Vector3.Distance(player.position, this.transform.position) > 30 && !isPatrolling)
{
WaitingOnAction();
}
And in your Coroutine:
IEnumerator BackToPatrol()
{
isPatrolling = true;
yield return new WaitForSeconds(5);
anim.SetBool("IsIdle", false);
yield return StartCoroutine("Patrol");
isPatrolling = false;
}
IEnumerator Patrol()
{
Debug.Log("In Patrol");
agent.speed = patrolSpeed;
agent.SetDestination(waypoints[waypointInd].transform.position);
anim.SetBool("WalkForwards", true);
agent.isStopped = false;
while (Vector3.Distance(this.transform.position, waypoints[waypointInd].transform.position) >= 2 && isPatrolling)
{
yield return null;
}
agent.isStopped = true;
anim.SetBool("WalkForwards", false);
waypointInd++;
if(waypointInd >= waypoints.Length) waypointInd = 0;
}
I didn't test it, but something like this should work.

Unity - collision on 3 sides

I have a problem with collision. Sometimes it works right, but when I move with blue object inside red object, collision changes side and works bad. For example I add ZIP file: here
Generator script:
public class Generator : MonoBehaviour
{
public GameObject obstaclePrefab;
Dictionary<string, GameObject> obstacles;
Dictionary<string, Quaternion> rotations; // default rotation = open to the left
void Start()
{
rotations = new Dictionary<string, Quaternion>()
{
{ "left", Quaternion.Euler(0,0,0) },
{ "down", Quaternion.Euler(0,0,90) },
{ "right", Quaternion.Euler(0,180,0) },
{ "up", Quaternion.Euler(0,0,270) }
};
obstacles = new Dictionary<string, GameObject>();
SpawnObstacle(new Vector2(3,0),"left");
}
void SpawnObstacle(Vector2 position, string openSide)
{
//TODO
print("SpawnObstacle()");
GameObject go = (GameObject)Instantiate(obstaclePrefab, position, rotations[openSide]);
go.GetComponent<Obstacle>().openSide = openSide;
string pos = position.x + "_" + position.y;
obstacles.Add(pos, go);
}
public GameObject GetObjectAt(Vector3 position)
{
string pos = position.x + "_" + position.y;
if (obstacles.ContainsKey(pos) == true)
{
print(obstacles[pos]);
return obstacles[pos];
}
else return null;
}
}
PlayerMove script:
public class PlayerMove : MonoBehaviour
{
public Generator generator;
Vector3 pos;
public float speed;
void Start()
{
pos = transform.position;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
GameObject go = generator.GetObjectAt(transform.position - new Vector3(speed, 0, 0));
if (go == null || go.GetComponent<Obstacle>().canEnterFromSide("left"))
{
print(go);
pos.x -= speed;
}
}
else if (Input.GetKeyDown(KeyCode.RightArrow))
{
GameObject go = generator.GetObjectAt(transform.position + new Vector3(speed, 0, 0));
if (go == null || go.GetComponent<Obstacle>().canEnterFromSide("right"))
{
print(go);
pos.x += speed;
}
}
else if (Input.GetKeyDown(KeyCode.UpArrow))
{
GameObject go = generator.GetObjectAt(transform.position + new Vector3(0, speed, 0));
if (go == null || go.GetComponent<Obstacle>().canEnterFromSide("up"))
{
print(go);
pos.y += speed;
}
}
else if (Input.GetKeyDown(KeyCode.DownArrow))
{
GameObject go = generator.GetObjectAt(transform.position - new Vector3(0, speed, 0));
if (go == null || go.GetComponent<Obstacle>().canEnterFromSide("down"))
{
print(go);
pos.y -= speed;
}
}
transform.position = Vector2.MoveTowards(transform.position, pos, speed);
}
void OnTriggerEnter2D(Collider2D col)
{
if (col.CompareTag("obstacle"))
{
col.gameObject.GetComponent<Obstacle>().Move(true);
print("obstacle");
}
/* else if (col.transform.root.GetComponent<Obstacle>().openSide == "left")
{
}*/
}
}
Obstacle script:
public class Obstacle : MonoBehaviour {
Vector3 pos;
GameObject player;
bool move = false;
public string openSide;
void Start () {
player = GameObject.FindWithTag("Player");
pos = transform.position;
}
public bool Move(bool mo)
{
if(mo)
move = true;
return move;
}
void Update () {
if (openSide == "left" && Input.GetKeyDown(KeyCode.LeftArrow))
move = false;
if (openSide == "right" && Input.GetKeyDown(KeyCode.RightArrow))
move = false;
if (openSide == "up" && Input.GetKeyDown(KeyCode.UpArrow))
move = false;
if (openSide == "down" && Input.GetKeyDown(KeyCode.DownArrow))
move = false;
if (move)
transform.position = player.transform.position;
}
public bool canEnterFromSide(string side)
{
return side == openSide;
}
}

Categories

Resources