I need some help . I work at a 2d unity game which have a fluffy ball as the main character . This fluffy ball have a hand component ( child ) which have a animation . Each individual frame have a box collider property .This hand will be activated when i press E and that animation will start in the direction where my cursor is . So , the problem is next : I want that hand to grab stuffs . Like a box . Here i ask for your help . i tried to figure out how i can freeze the aniamation for a short time , like 5 seconds or till i press again E , when the box collider of that specific frame collide with a object (e.g. ground or box ).Here is the script of the hand :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class facingScript : MonoBehaviour
{
private SpriteRenderer render;
private Camera mainCam;
private Vector3 mousePos;
private Animator aniHand;
public bool freezeAniamtion = false;
void Start()
{
render = GetComponent<SpriteRenderer>();
mainCam = Camera.main;
gameObject.SetActive(false);
aniHand = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
mousePos = Input.mousePosition;
mousePos = mainCam.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, mainCam.transform.position.z - transform.position.z));
Vector3 rotation = mousePos - transform.position;
if(rotation.x > 0)
render.flipY = true;
else
render.flipY = false;
if(Input.GetKeyDown(KeyCode.E))
{
aniHand.Play("CharacterHand");
}
}
void OnCollisionEnter2D(Collision2D collision)
{
if(collision.gameObject.tag == "box")
{
StartCoroutine(HandCollide());
// help pls :)
}
}
private IEnumerator HandCollide(float waitTime)
{
// idk what i should put here :P
}
}`
I try with aniHand.speed but it dont do nothing and with PlayInFixedTime but idk how it work
So . I fugire it out some how . I have another script that activate and dezactivate my hand for 1 second. And when I try to stop my animation în hand script it just turn of from that another script
Related
I am a beginner in Unity and I am currently making a simple game. I have a problem where upon initial collision, the event that I wanted to happen does not trigger or in other words the OnCollisionEnter is not working upon initial collision.
The process of my script is when colliding which is the OnCollisionEnter the button will appear or it will be set active to true. But in the first collision it does not trigger or it is not working, I need to walk away a bit and go back in that way it only works. Sometimes I need to do it 2 or more times for the collider to trigger. I don't know if the script has problem or the collider itself but I made sure it is colliding properly when I look at the editor.
I set the object to static so it will not be pushed when walking and colliding towards it. I wonder if that has to do with this problem because even disabled it is the same. But can anyone give suggestions on how not to make the objects move or be pushed away upon collision?
Here is the script for my collision:
using UnityEngine;
using UnityEngine.UI;
public class InteractNPC : MonoBehaviour
{
//public Button UI;
[SerializeField] GameObject uiUse, nameBtn;
private Transform head;
private Vector3 offset = new Vector3(0, 1.0f, 0);
// Start is called before the first frame update
void Start()
{
//uiUse = Instantiate(UI, FindObjectOfType<Canvas>().transform).GetComponent<Button>();
uiUse.gameObject.SetActive(true);
head = transform.GetChild(0);
uiUse.transform.position = Camera.main.WorldToScreenPoint(head.position + offset);
}
// Update is called once per frame
void Update()
{
uiUse.transform.position = Camera.main.WorldToScreenPoint(head.position + offset);
nameBtn.transform.position = Camera.main.WorldToScreenPoint(head.position + offset);
}
private void OnCollisionEnter(Collision collisionInfo)
{
//Debug.Log("wews2");
if(collisionInfo.collider.name == "Player")
{
nameBtn.gameObject.SetActive(true);
}
}
private void OnCollisionExit(Collision collisionInfo)
{
if(collisionInfo.collider.name == "Player")
{
nameBtn.gameObject.SetActive(false);
}
}
}
Here is another script with collision and has the same problem:
using UnityEngine;
using UnityEngine.UI;
public class InteractButtonPosition : MonoBehaviour
{
//public Button UI;
[SerializeField] GameObject uiUse;
private Vector3 offset = new Vector3(0, 0.5f, 0);
// Start is called before the first frame update
void Start()
{
//uiUse = Instantiate(UI, FindObjectOfType<Canvas>().transform).GetComponent<Button>();
//uiUse = GameObject.FindGameObjectWithTag("ViewButton");
}
// Update is called once per frame
void Update()
{
uiUse.transform.position = Camera.main.WorldToScreenPoint(this.transform.position + offset);
}
private void OnCollisionEnter(Collision collisionInfo)
{
if(collisionInfo.collider.name == "Player")
{
Debug.Log("wews");
uiUse.gameObject.SetActive(true);
}
}
private void OnCollisionExit(Collision collisionInfo)
{
if(collisionInfo.collider.name == "Player")
{
//Destroy(uiUse.gameObject);
uiUse.gameObject.SetActive(false);
}
}
}
Try changing Colision detection from Descrete to Continuous
collission detection
I solved this issue by using OntriggerEnter instead of OnCollisionEnter. In the editor, for the NPC I put a Collider on each part of the body and check the IsTrigger in the parent Object so it will still collide with my character even if the IsTrigger is enabled that will make the character go through the object. I just enlarged the scale of the collider with IsTrigger enabled so the collision will be detected immediately.
I want to move my player around in my level without a NavMesh Agent.
I was thinking something about raycasting, but i have tried everything and even looked up videos and searched on google about it, can't seem to find anything that works
Plz help!
you can use this for moving to mouseclick position.
This method will move object or player to the position where mouse is clicked on screen.
sorry for syntax error i have typed directly here
using UnityEngine;
using System.Collections;
public class MouseMovement : MonoBehaviour
{
public float speed = 10f;
bool isplayermove = false;
// Use this for initialization
private void Start ()
{
Vector3 playerpos = transform.position;
}
// Update is called once per frame
private void Update ()
{
if (Input.GetKeyDown(KeyCode.Mouse0))
{
is moveplayer = true;
}
if(ismoveplayer)
{
Vector3 mousePos = Camera.main.ScreenToWorldPoint(new Vector3(input.mousepos.x,input.mousepos.y,input.mousepos.z);
transform.position = Vector3.MoveTowards(transform.position,new Vector3(mousepos.x,transform.position.y,mousepos.z),speed * time.deltatime);
if(transform.position == mousepos)
{
ismoveplayer = false;
}
}
}
}
I'm working on a RTS game. I did a normal move script and I increase the agent's stopping distance so they don't look at each other and pump that much. But they still hit each other.
I can't find the way to make agents avoid each other and not push each other. Or someway to ignore the physics while still trying to avoid each other. Here is the code for the click to move
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class moveTest : MonoBehaviour {
NavMeshAgent navAgent;
public bool Moving;
// Use this for initialization
void Start () {
navAgent = GetComponent<NavMeshAgent>();
}
// Update is called once per frame
void Update () {
move();
}
void move()
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Input.GetMouseButtonDown(1))
{
Moving = true;
if (Moving)
{
if (Physics.Raycast(ray, out hit, 1000))
{
navAgent.SetDestination(hit.point);
navAgent.Resume();
}
}
}
}
}
From the following link (which sadly don´t have images anymore)
Modify the avoidancePriority. You can set the enemie´s value of
30 or 40 for example.
Add a NavMeshObstacle component to the "enemy" prefab
Use this script for the Enemy Movement
Script
using UnityEngine;
using System.Collections;
public class enemyMovement : MonoBehaviour {
public Transform player;
NavMeshAgent agent;
NavMeshObstacle obstacle;
void Start () {
agent = GetComponent< NavMeshAgent >();
obstacle = GetComponent< NavMeshObstacle >();
}
void Update () {
agent.destination = player.position;
// Test if the distance between the agent and the player
// is less than the attack range (or the stoppingDistance parameter)
if ((player.position - transform.position).sqrMagnitude < Mathf.Pow(agent.stoppingDistance, 2)) {
// If the agent is in attack range, become an obstacle and
// disable the NavMeshAgent component
obstacle.enabled = true;
agent.enabled = false;
} else {
// If we are not in range, become an agent again
obstacle.enabled = false;
agent.enabled = true;
}
}
}
Basically the issue that this approach tries to solve is when the player is surrounded by enemies, those which are in range to attack (almost touching the player) stop moving to attack, but the enemies in the second or third row are still trying to reach the player to kill him. Since they continue moving, they push the other enemies and the result is not really cool.
So with this script, when an enemy is in range to attack the character, it becomes an obstacle, so other enemies try to avoid them and instead of keep pushing, go around looking for another path to reach the player.
Hope it can help you some how
I am pretty fluent in using Unity, but regarding Mechanim and Animations I am not the too great at currently, so please don't give me too much of a hard time lol. So I have this boolean that is in my GameManager script:
public bool countDownDone = false;
This boolean gets set to true once my "3,2,1, GO!" Countdown Timer ends at the beginning of my game. Everything in my game starts after that boolean is set to true. Example:
using UnityEngine;
using System.Collections;
public class PlaneMover : MonoBehaviour {
private GameManagerScript GMS; // Reference to my GameManager Script
public float scrollSpeed;
public float tileSizeZAxis;
public float acceleration; //This has to be a negative number in the inspector. Since our plane is coming down.
private Vector3 startPosition;
void Start () {
GMS = GameObject.Find ("GameManager").GetComponent<GameManagerScript> (); //Finds the Script at the first frame
// Transform position of the quad
startPosition = transform.position;
}
void Update () {
if (GMS.countDownDone == true) //Everything starts once the countdown ends.
{
/* Every frame - time in the game times the assigned scroll speed
and never exceed the length of the tile that we assign */
float newPosition = Mathf.Repeat (Time.time * scrollSpeed, tileSizeZAxis);
// New position equal to the start position plus vector3forward times new position
transform.position = startPosition + Vector3.forward * newPosition; // was vector3.forward
scrollSpeed += Time.deltaTime * acceleration; // This makes the plane increase in speed over time with
// whatever our acceleration is set to.
}
}
}
I have this Crawling animation that plays at the very beginning of the game (Even before the Timer ends) and loops forever. My question is , how do I make that crawling animation also start once that boolean is set to "true"? Or do I just apply it to a CoRoutine and make it play after 3 seconds? I have done extensive research on whether to reference Animation or Animator and I got confused on that too. Any advice? If you need more pictures or details on my question, just let me know. Thank you! :)
NEW CODE BELOW
using UnityEngine;
using System.Collections;
public class Crawling : MonoBehaviour {
Animator animator;
private GameManagerScript GMS;
void Start ()
{
animator = GetComponent<Animator> ();
GMS = GameObject.Find ("GameManager").GetComponent<GameManagerScript> ();
}
void Update ()
{
if (GMS.countDownDone == true)
{
animator.Play("Main Character Crawling", 1);
}
}
}
I have this Crawling animation that plays at the very beginning of the
game (Even before the Timer ends) and loops forever. My question is ,
how do I make that crawling animation also start once that boolean is
set to "true"?
The solution is to play the animation from script.
Remove the currentAnimation.
Select the GameObject your PlaneMover script is attached to, attach Animation and Animator components to it. Make sure that the Animation's Play Automatically is unchecked.
public class PlaneMover : MonoBehaviour {
private GameManagerScript GMS; // Reference to my GameManager Script
public float scrollSpeed;
public float tileSizeZAxis;
public float acceleration; //This has to be a negative number in the inspector. Since our plane is coming down.
private Vector3 startPosition;
Animation animation;
public AnimationClip animationClip; //Assign from Editor
void Start () {
GMS = GameObject.Find ("GameManager").GetComponent<GameManagerScript> (); //Finds the Script at the first frame
// Transform position of the quad
startPosition = transform.position;
animation = GetComponent<Animation>();
//Add crawing Animation
animation.AddClip(animationClip, "Crawling");
//Add other animation clips here too if there are otheres
}
void Update ()
{
if (GMS.countDownDone) //Everything starts once the countdown ends.
{
/* Every frame - time in the game times the assigned scroll speed
and never exceed the length of the tile that we assign */
float newPosition = Mathf.Repeat (Time.time * scrollSpeed, tileSizeZAxis);
// New position equal to the start position plus vector3forward times new position
transform.position = startPosition + Vector3.forward * newPosition; // was vector3.forward
scrollSpeed += Time.deltaTime * acceleration; // This makes the plane increase in speed over time with
// whatever our acceleration is set to.
//Play Animation
animation.PlayQueued("Crawling", QueueMode.CompleteOthers);
}
}
} }
I solved the problem!!
This is my script:
using UnityEngine;
using System.Collections;
public class Crawling : MonoBehaviour {
public Animator animator;
private GameManagerScript GMS;
void Start ()
{
animator = GetComponent<Animator> ();
GMS = GameObject.Find ("GameManager").GetComponent<GameManagerScript> ();
}
void Update ()
{
if (GMS.countDownDone == true) {
animator.enabled = true;
}
else
{
animator.enabled = false;
}
}
}
All I do is just enable the Animator that I attach in the Inspector whenever "countDownDone" becomes "true", and for added safety, I added the "else" for it to be disabled. If someone notices a way for me to improve this script, please let me know. Thank you :)
Shorter version:
if (GMS.countDownDone)
animator.enabled = true;
else
animator.enabled = false;
I have the following code, but i'm having some problems. Every time update is called, the character move to the point i give him to. But i just give him a point when i click with the mouse on the ground, the problem starts when i try to make it animate the character.
If i pass the value of the animation on the clickToMove() method it'll always play that animation even if we aren't moving. And if i place clickToMove inside the "if clicked" the character will teleport and not move towards. I can't think in a way to do the animation properly, only when the object is moving, and goes back to idle when it's stopped, even if the clickToMove() is playing all the time.
using UnityEngine;
using System.Collections;
public class ClickScript : MonoBehaviour
{
public float moveSpeed;
public float minDistance;
Vector3 mouseClick; //Creates a variable to save the constant of the hit from raycast
private Animator anim;
private Rigidbody rigidB;
// Use this for initialization
void Start()
{
anim = GetComponent<Animator>();
rigidB = GetComponent<Rigidbody>();
}
// Update is called once per frame
void FixedUpdate()
{
if (Input.GetMouseButtonDown(1))//If clicked
{
clickPosition(); //Gets the click position
}
if (Vector3.Distance(transform.position, mouseClick) > minDistance) //If the click distance is bigger than the minimal
{
//It is allways moving, but since there's no click position it doesn't move when not clicked
clickToMove();
}
}
void clickPosition()//This function throw a raycast on the ground and save the position on mouseClick to make the char move to there
{
RaycastHit clickHit; //creates a constant with the infos from the raycast
Ray mouseClickPosition = Camera.main.ScreenPointToRay(Input.mousePosition); //creates a constant to save the mouse position
if (Physics.Raycast(mouseClickPosition, out clickHit, 100.00f))//throw a raycast returning the mouse position and more infos
{
Debug.Log("Click at " + clickHit.point); //Show where were clicked
mouseClick = clickHit.point;//mouseClick receive the position of the click
}
}
void clickToMove() //this function make the player look at the click and move to mouseClick
{
mouseClick.y = transform.position.y; //get rid of the y to fix rotation bugs
transform.LookAt(mouseClick);//look at the poit you clicked
transform.position = Vector3.MoveTowards(transform.position, mouseClick, moveSpeed * Time.deltaTime);//move to the clickpoint
}
}
How about this way?
bool _isAnimating = false;
// Update is called once per frame
void FixedUpdate()
{
if (Input.GetMouseButtonDown(1))//If clicked
{
clickPosition(); //Gets the click position
//start animation here!!!
//animator.SetBool("bWalk", false);
//and set animation state to true
_isAnimating = true;
}
if (Vector3.Distance(transform.position, mouseClick) > minDistance)
{
clickToMove();
}
else if(_isAnimating)
{
//turn off the animation here!!!
//animator.SetBool("bStop", false);
//and set to false
_isAnimating = false;
}
}