Basically what the title asks. I want to play my animation, then after the animation is finished playing, I want there to be a small delay before it fades out of the scene in about 2 seconds. After it fades out, it should be disabled and reset.
Here's my code so far, but when I set unlocking to true, it does nothing.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AnimationController : MonoBehaviour
{
public Animator anim;
public SpriteRenderer sr;
public bool unlocking;
Sprite unlockSprite;
Sprite lockSprite;
Color temp;
// Start is called before the first frame update
void Start()
{
unlocking = false;
unlockSprite = Resources.Load<Sprite>("unlock");
lockSprite = Resources.Load<Sprite>("lock");
}
// Update is called once per frame
void Update()
{
if (unlocking) {
anim.Play("unlock");
unlocking = false;
sr.sprite = unlockSprite;
System.Threading.Thread.Sleep(1000);
StartCoroutine(FadeTo(0.0f, 2.0f));
temp = new Color(sr.color.r, sr.color.g, sr.color.b, 0f);
sr.color = temp;
gameObject.SetActive(false);
sr.sprite = lockSprite;
temp = new Color(sr.color.r, sr.color.g, sr.color.b, 1f);
sr.color = temp;
}
}
IEnumerator FadeTo(float aValue, float aTime)
{
float alpha = sr.color.a;
for (float t = 0.0f; t < 1.0f; t += Time.deltaTime / aTime)
{
Color newColor = new Color(sr.color.r, sr.color.g, sr.color.b, Mathf.Lerp(alpha, aValue, t));
sr.color = newColor;
yield return null;
}
}
}
UPDATED CODE:
anim.Play("unlock");
unlocking = false;
if (animInfo.normalizedTime >= 1)
{
anim.enabled = false;
sr.sprite = unlockSprite;
StartCoroutine(FadeTo(0.0f, 2.0f));
temp = new Color(sr.color.r, sr.color.g, sr.color.b, 0f);
sr.color = temp;
gameObject.SetActive(false);
sr.sprite = lockSprite;
temp = new Color(sr.color.r, sr.color.g, sr.color.b, 1f);
sr.color = temp;
}
One of ways to pull it off, is to make another coroutine, something like that:
IEnumerator UnlockSequence()
{
while (animInfo.normalizedTime < 1.0f)
{
yield return null;
}
anim.enabled = false;
sr.sprite = unlockSprite;
yield return new WaitForSeconds(1.0f);
yield return StartCoroutine(FadeTo(0.0f, 2.0f));
// everything else
}
Related
What Whip should look like
I'm trying to create a whip that can extend in any direction the mouse is facing after pressing a certain button. If there are "grabbable" objects in the way such as an enemy or box, it should latch onto those objects and pull them around to collide with other objects for a certain amount of time.
I know that I need the different sprite shots of the whip extending and latching for animation, but I have no idea how to implement this in code and how to get the whip to stop short if it detects a "grabbable" object.
Attach this script to your player, this should get the job done:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public Transform player = null;
public float speed = 30f;
public string grabbableTag = "grabbable";
private LineRenderer line = null;
private float timer = 0f;
private bool grabbing = false;
private bool reached = false;
private Vector2 from = Vector2.zero;
private Vector2 to = Vector2.zero;
private Vector2 target = Vector2.zero;
private Transform grabbable = null;
private void Start()
{
player = transform;
line = new GameObject("Line").AddComponent<LineRenderer>();
line.startColor = Color.red;
line.endColor = Color.red;
// Assign a material
line.gameObject.SetActive(false);
reached = false;
grabbing = false;
}
private void Update()
{
if(grabbing)
{
Grabbing();
}
else
{
if (Input.GetMouseButtonDown(0))
{
Grab();
}
}
}
private void Grab()
{
Vector3 mousePosition = Input.mousePosition;
mousePosition.z = Vector3.Distance(player.position, Camera.main.transform.position);
to = Camera.main.ScreenToWorldPoint(mousePosition);
from = player.position;
Vector2 direction = (to - from).normalized;
float distance = Vector2.Distance(from, to);
RaycastHit2D[] hits = Physics2D.RaycastAll(from, direction, distance);
grabbable = null;
for (int i = 0; i < hits.Length; i++)
{
if (hits[i].transform.tag == grabbableTag)
{
grabbable = hits[i].transform;
break;
}
}
if (grabbable != null)
{
distance = Vector2.Distance(player.position, grabbable.position);
to = from + direction * distance;
}
grabbing = true;
reached = false;
target = from;
timer = 0;
line.gameObject.SetActive(true);
line.positionCount = 2;
line.SetPosition(0, from);
line.SetPosition(1, from);
}
private void Grabbing()
{
if (reached)
{
target = Vector2.Lerp(target, from, speed * Time.deltaTime);
if (target == from)
{
GrabDone(grabbable);
grabbing = false;
line.gameObject.SetActive(false);
}
}
else
{
target = Vector2.Lerp(target, to, speed * Time.deltaTime);
if(target == to)
{
reached = true;
}
}
line.SetPosition(1, target);
if (reached && grabbable != null)
{
grabbable.position = target;
}
}
private void GrabDone(Transform grabbed)
{
if(grabbed != null)
{
// Do somthing ...
Destroy(grabbed.gameObject);
}
}
}
I know the title might be misleading after you see what is the problem, but I really don't know how to name this issue.
The first picture shows the problem.
The white line shows the distance between the player and the gameobject called hook. The blue sprite sphere close to the hook is the SpringJoint2D.connectedBody.
They both (the white line and the blue sprite) are working with the same value: hook.transform.position.
Here is the code snippets which I believe are causing problems or at least reveal the most:
SpringJoint2D snippet:
if (Input.GetMouseButtonDown(0))
{
hook = FindClosestObject(radius, "Hook");
if(hook != null)
{
joint.enabled = true;
joint.connectedBody = hook;
joint.connectedAnchor = hook.transform.position;
Debug.Log("Click.");
Debug.Log(hook);
}
}
if (Input.GetMouseButtonUp(0))
{
joint.enabled = false;
joint.connectedBody = null;
}
Debug.DrawLine snippet:
if (hook != null)
{
joint.distance = Vector3.Distance(hook.transform.position, transform.position) / 2;
Debug.DrawLine(transform.position, hook.transform.position);
}
And here is the whole code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerScript : MonoBehaviour
{
public float radius;
private SpringJoint2D joint;
private Rigidbody2D hook = new Rigidbody2D();
// Start is called before the first frame update
void Start()
{
joint = GetComponent<SpringJoint2D>();
}
// Update is called once per frame
void Update()
{
//touch.phase == TouchPhase.Began
if (Input.GetMouseButtonDown(0))
{
hook = FindClosestObject(radius, "Hook");
if(hook != null)
{
joint.enabled = true;
joint.connectedBody = hook;
joint.connectedAnchor = hook.transform.position;
Debug.Log("Click.");
Debug.Log(hook);
}
}
if (Input.GetMouseButtonUp(0))
{
joint.enabled = false;
joint.connectedBody = null;
}
//foreach (Touch touch in Input.touches)
//{
//}
if (hook != null)
{
joint.distance = Vector3.Distance(hook.transform.position, transform.position) / 2;
Debug.DrawLine(transform.position, hook.transform.position);
}
}
private void OnDrawGizmos()
{
Gizmos.color = Color.green;
Gizmos.DrawWireSphere(transform.position, radius);
if (hook != null)
Gizmos.DrawLine(transform.position, hook.transform.position);
}
public Rigidbody2D FindClosestObject(float radius, string tag)
{
GameObject[] gos;
gos = GameObject.FindGameObjectsWithTag(tag);
Rigidbody2D closest = null;
float distance = radius;
Vector3 position = transform.position;
foreach (GameObject go in gos)
{
Vector3 diff = go.transform.position - position;
float curDistance = diff.sqrMagnitude;
if (curDistance < distance)
{
closest = go.GetComponent<Rigidbody2D>();
distance = curDistance;
}
}
return closest;
}
}
Ah, I was just stupid.
There is no need to assign the connectedAnchor if you also asign the connectedRigidbody2D
The connectedAnchor is the offset from the connectedRigidbody2D's position...
I need some help to swipe object or we can say move object on which i have touched.
I have created code in which i'm able to drag only one button.
Suppose i touched on first button it should be active for swipe.
Here is my screen show.
I want to create code for every button for dragging that button on Swipe.
Here is my buttons
using UnityEngine;
public class SwipeJump : MonoBehaviour
{
private Vector2 startTouchPosition, endTouchPosition;
private Rigidbody2D rb;
private float jumpForce = 700f;
private bool jumpAllowed = false;
float deltaX, deltaY;
// Use this for initialization
private void Start ()
{
rb = GetComponent<Rigidbody2D> ();
#region newcode
PhysicsMaterial2D mat = new PhysicsMaterial2D();
//mat.bounciness = 0.75f;
//mat.friction = 0.4f;
GetComponent<CircleCollider2D>().sharedMaterial = mat;
#endregion
}
// Update is called once per frame
private void Update ()
{
//SwipeCheck ();
#region newcode
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
Vector2 touchPos = Camera.main.ScreenToWorldPoint(touch.position);
switch (touch.phase)
{
case TouchPhase.Began:
if (GetComponent<Collider2D>() == Physics2D.OverlapPoint(touchPos))
{
deltaX = touchPos.x - transform.position.x;
deltaY = touchPos.y - transform.position.y;
jumpAllowed = true;
rb.freezeRotation = true;
rb.velocity = new Vector2(0, 0);
rb.gravityScale = 0;
GetComponent<Collider2D>().sharedMaterial = null;
}
break;
case TouchPhase.Moved:
if (GetComponent<Collider2D>() == Physics2D.OverlapPoint(touchPos) && jumpAllowed)
{
rb.MovePosition(new Vector2(touchPos.x - deltaX, touchPos.y - deltaY));
}
break;
case TouchPhase.Ended:
jumpAllowed = false;
rb.freezeRotation = false;
rb.gravityScale = 2;
PhysicsMaterial2D mat = new PhysicsMaterial2D();
//mat.bounciness = 0.75f;
//mat.friction = 0.4f;
GetComponent<CircleCollider2D>().sharedMaterial = mat;
break;
}
}
#endregion
}
}
Complete newbie here. Using Unity C#. I'm looking at moving my PONG game from keyboard control to touch screen. Here is my working keyboard code:
// Player 1 => Controls left bat with W/S keys
public GameObject leftBat;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
//Defualt speed of the bat to zero on every frame
leftBat.GetComponent<Rigidbody>().velocity = new Vector3(0f, 0f, 0f);
//If the player is pressing the W key...
if (Input.GetKey (KeyCode.W)) {
//Set the velocity to go up 1
leftBat.GetComponent<Rigidbody>().velocity = new Vector3(0f, 8f, 0f);
}
//If the player is pressing the S key...
else if (Input.GetKey (KeyCode.S)) {
//Set the velocity to go down 1 (up -1)
leftBat.GetComponent<Rigidbody>().velocity = new Vector3(0f, -8f, 0f);
}
}
I found this code and been playing around with it but to now avail.
using UnityEngine;
using System.Collections;
public class Player_Input_Controller : MonoBehaviour {
public GameObject leftBat;
public float paddleSpeed = 1f;
public float yU;
public float yD;
private Ray ray;
private RaycastHit rayCastHit;
private Vector3 playerPos = new Vector3(0, -9.5f, 0);
// Update is called once per frame
void Update () {
if (Input.GetMouseButton (0))
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray, out rayCastHit)){
Vector3 position = rayCastHit.point;
float yPos = position.y;
playerPos = new Vector3(Mathf.Clamp(yPos, yU, yD), -9.5f, 0f);
transform.position = playerPos;
}
}
}
}
Any one have a touchscreen Pong script I could use, or know how to edit this one?
Again, I'm really new and I'm sorry if I look like the Dummy in the class.
Thanks for any help provided. I REALLY appreciate it. This is the last hurdle in completing my game.
In my opinion, you do not need any raycasting. Because you are working in 2D and you are only concerned about the y value of Input.mousePosition. Therefore, you can calculate the extent of your screen using your camera's z value. If your camera is at (0, 0, -10) lets say your extents in the game will be -5 - BatOffset to 5+BatOffset in your world coordinates. Therefore, you somehow need a function to map Screen.height to your world coordinate extents as you can see from the image.
In conclusion you need to find Input.mousePosition.y divide it to Screen.height. This will give you the ratio where you touch or click. Then find the position in world space.
Note that: you can also use Input.touchPosition.y. Following script will work for you to do this operation:
public GameObject cam;
private Vector3 batPos;
private float minY;
private float maxY;
private int Res;
private float deltaY;
void Start () {
minY = cam.transform.position.z / 2 - gameObject.transform.localScale.y;
maxY = (-cam.transform.position.z / 2) + gameObject.transform.localScale.y;
deltaY = maxY - minY;
Debug.Log(minY + " " + maxY + " " + deltaY);
Res = Screen.height;
batPos = gameObject.transform.position;
}
void Update () {
if(Input.GetMouseButtonDown(0))
{
// we find the height we have to go up from minY
batPos.y =minY + Input.mousePosition.y / Res * deltaY;
gameObject.transform.position = batPos;
}
}
This works for me in the editor when you click on screen with mouse. You just have to change the parts Input.GetMouseButtonDown to Touch commands such as Touch.tapCount > 0. Also this script should be attached to the bat. Good luck!
Also You can use Orthographic camera and Orthographic camera size instead of cam.transformation.z
May be helpfull
create script. for example player.cs
public class PlayerController : MonoBehaviour
{
bool swipeRight = false;
bool swipeLeft = false;
bool touchBlock = true;
bool canTouchRight = true;
bool canTouchLeft = true;
void Update()
{
swipeLeft = Input.GetKeyDown("a") || Input.GetKeyDown(KeyCode.LeftArrow);
swipeRight = Input.GetKeyDown("d") || Input.GetKeyDown(KeyCode.RightArrow);
TouchControl();
if(swipeRight) //rightMove logic
else if(swipeLeft) //leftMove logic
}
void TouchControl()
{
if(Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Began )
{
//Jump logic
}
else if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved && touchBlock == true)
{
touchBlock = false;
// Get movement of the finger since last frame
var touchDeltaPosition = Input.GetTouch(0).deltaPosition;
Debug.Log("touchDeltaPosition "+touchDeltaPosition);
if(touchDeltaPosition.x > 0 && canTouchRight == true)
{
//rightMove
swipeRight = true; canTouchRight = false;
Invoke("DisableSwipeRight",0.2f);
}
else if(touchDeltaPosition.x < 0 && canTouchLeft == true)
{
//leftMove
swipeLeft = true; canTouchLeft = false;
Invoke("DisableSwipeLeft",0.2f);
}
}
}
void DisableSwipeLeft()
{
swipeLeft = false;
touchBlock = true;
canTouchLeft = true;
}
void DisableSwipeRight()
{
swipeRight = false;
touchBlock = true;
canTouchRight = true;
}
}
I've written the following code making the gun move to the guy's shoulder position when he stops shooting and it does work...BUT ONLY ONCE. After that, it starts not to meet the target even though it's coordinates remain the same. I've tried it with Lerp, SmoothDamp, MoveTowards...still don't get where the problem lies.
P.S. The gun moves to the shoulder when shooting perfectly, it starts happening when the character stops shooting and tries to go back to the Idle pose.
EDIT: Turns out there's also something wrong with rotation...or maybe it's just rotation. I don't even know at this point.
THE VIDEO of what's going on: https://youtu.be/CheQiomYtm8
THE CODE:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnitControl;
public class BlastIKController : MonoBehaviour
{
public WeaponState wpState;
public GameObject weapon;
public GameObject RightShoulder;
public GameObject HumanSpine;
public GameObject WeaponSpawn;
public LayerMask lmask;
public BlastIKHandler ikHandle;
public Material targetMat;
public Material defMat;
public GameObject target;
public GameObject WeaponIdle;
public bool isShooting = false;
//public bool InIdle = true;
LineRenderer ShootLine;
public GameObject WeaponInstance;
Animator anim;
public float speedMove;
public float speedRot;
// Use this for initialization
void Awake()
{
GameObject weaponInst = Instantiate(weapon, WeaponSpawn.transform);
WeaponInstance = weaponInst;
WeaponInstance.transform.localPosition = new Vector3(0, 0, 0);
wpState = weaponInst.GetComponent<WeaponState>();
ikHandle = this.GetComponent<BlastIKHandler>();
ShootLine = this.GetComponent<LineRenderer>();
anim = this.GetComponent<Animator>();
ikHandle.RightShoulder = RightShoulder;
ikHandle.leftHandTarget = wpState.leftHandIdle.transform;
ikHandle.rightHandTarget = wpState.rightHandTarget.transform;
//Позиция оружия
wpState.shoulder.transform.position = ikHandle.WeaponIdlePos.position;
wpState.shoulder.transform.rotation = ikHandle.WeaponIdlePos.rotation;
}
// Update is called once per frame
void Update()
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
#region SearchTarget
if (Physics.Raycast(ray, out hit, Mathf.Infinity, lmask))
{
if (hit.collider.gameObject.tag == "Target")
{
ShootLine.positionCount = 2;
ShootLine.SetPosition(0, HumanSpine.transform.position);
ShootLine.SetPosition(1, hit.collider.gameObject.transform.position);
if (Input.GetMouseButton(0))
{
if (target == null)
{
target = hit.collider.gameObject;
MeshRenderer ms = hit.collider.gameObject.GetComponent<MeshRenderer>();
ms.material = targetMat;
ikHandle.targetPos = hit.collider.gameObject;
}
else
{
MeshRenderer ms = target.GetComponent<MeshRenderer>();
ms.material = defMat;
target = hit.collider.gameObject;
ms = target.GetComponent<MeshRenderer>();
ms.material = targetMat;
ikHandle.targetPos = hit.collider.gameObject;
}
}
}
}
#endregion
#region Shooting
Shooting();
if (isShooting)
{
if (target != null)
{
bool isShoot = anim.GetBool("Shoot");
if (!isShoot)
{
StartCoroutine(MoveToShoot(RightShoulder.transform.position));
ikHandle.leftHandTarget = wpState.leftHandTarget.transform;
anim.SetBool("Shoot", true);
//InIdle = false;
}
}
}
else
{
// float stepMove = speedMove * Time.deltaTime;
// wpState.shoulder.transform.position = Vector3.Lerp(wpState.shoulder.transform.position, ikHandle.WeaponIdlePos.position, stepMove);
// //if (!InIdle)
// //{
// // StartCoroutine(MoveToIdle(ikHandle.WeaponIdlePos.position));
//// }
// //InIdle = true;
// //float stepMove = speedMove * Time.deltaTime;
// //while (wpState.shoulder.transform.position != ikHandle.WeaponIdlePos.position)
// //{
// // wpState.shoulder.transform.position = Vector3.Lerp(wpState.shoulder.transform.position, ikHandle.WeaponIdlePos.position, stepMove);
// //}
// ////wpState.shoulder.transform.position = ikHandle.WeaponIdlePos.position;
// ////wpState.shoulder.transform.position = Vector3.MoveTowards(wpState.shoulder.transform.position, ikHandle.WeaponIdlePos.position, stepMove);
// float stepRot = speedRot * Time.deltaTime;
// //while (wpState.shoulder.transform.rotation != ikHandle.WeaponIdlePos.rotation)
// //{
// wpState.shoulder.transform.rotation = Quaternion.Slerp(wpState.shoulder.transform.rotation, ikHandle.WeaponIdlePos.rotation, stepRot);
// //}
// ////wpState.shoulder.transform.rotation = ikHandle.WeaponIdlePos.rotation;
// ikHandle.leftHandTarget = wpState.leftHandIdle.transform;
// anim.SetBool("Shoot", false);
}
#endregion
}
void LateUpdate()
{
if (!isShooting)
{
float stepMove = speedMove * Time.deltaTime;
stepMove += Time.deltaTime / speedMove;
Vector3 velocity = Vector3.zero;
//.shoulder.transform.position = Vector3.Lerp(wpState.shoulder.transform.position, ikHandle.WeaponIdlePos.position, stepMove);
wpState.shoulder.transform.position = Vector3.MoveTowards(wpState.shoulder.transform.position, ikHandle.WeaponIdlePos.position, stepMove);
//wpState.shoulder.transform.position = Vector3.SmoothDamp(wpState.shoulder.transform.position, ikHandle.WeaponIdlePos.position, ref velocity, stepMove);
// wpState.shoulder.transform.position = Vector3.SmoothDamp()
float stepRot = speedRot * Time.deltaTime;
wpState.shoulder.transform.rotation = Quaternion.Slerp(wpState.shoulder.transform.rotation, ikHandle.WeaponIdlePos.rotation, stepRot);
ikHandle.leftHandTarget = wpState.leftHandIdle.transform;
anim.SetBool("Shoot", false);
}
}
void Shooting()
{
if (Input.GetKeyDown(KeyCode.S))
{
isShooting = !isShooting;
}
}
IEnumerator MoveToShoot(Vector3 WPposition)
{
float step = speedMove * Time.deltaTime;
while (wpState.shoulder.transform.position != WPposition)
{
wpState.shoulder.transform.position = Vector3.Lerp(wpState.shoulder.transform.position, WPposition, step);
Vector3 relativeWeaponPos = ikHandle.targetPos.transform.position - wpState.shoulder.transform.position;
Quaternion WeaponRotation = Quaternion.LookRotation(relativeWeaponPos);
wpState.shoulder.transform.rotation = Quaternion.Slerp(wpState.shoulder.transform.rotation, WeaponRotation, step);
yield return null;
}
}
IEnumerator MoveToIdle(Vector3 WPposition)
{
float stepMove = speedMove * Time.deltaTime;
float stepRot = speedRot * Time.deltaTime;
while (wpState.shoulder.transform.position != WPposition)
{
wpState.shoulder.transform.position = Vector3.Lerp(wpState.shoulder.transform.position, WPposition, stepMove);
wpState.shoulder.transform.rotation = Quaternion.Slerp(wpState.shoulder.transform.rotation, ikHandle.WeaponIdlePos.transform.rotation, stepRot);
yield return null;
}
wpState.shoulder.transform.position = Vector3.Lerp(wpState.shoulder.transform.position, ikHandle.WeaponIdlePos.position, stepMove);
}
}
So, it was the following. It turns out that the coroutines got mixed up in Update and they worked at the same time.
So...I removed all coroutines from the code and then moved and rotated using Lerp and sLerp in the update.
There's one thing though, I also had to add a check for both bositions to meet, and after that it starts shooting and only then.
P.S. I can add the code I changed later if you like.