Sorry for what is probably an easy problem, but I am having trouble wrapping my head around the new animation system.
I have a scene which has a mechanic like bending the two halves of a crane. These are controlled by levers that are sensitive to the amount dragged by the mouse.
My process is:
determine user click over gameobject and save input.mouseposition
calculate mouse movement on y axis and turn that into a float to be used to set animation speed (simulates feathering)
Try to set that float to animator.speed
I don’t have the code posted as it has been a miserable failure each time. Either the animation jumps to the other or there is very odd blending. The one time I got it close, there was a long pause each time whenever I got to either end of the animation.
Any chance anyone has done something similar or know a good resource for me? I’m gaining grey hair here and cant find anything after about a day of searching various forums.
Hmm ok, guess I was stuck on that idea since it was used a lot in the previous animation system. What is the new way to go about setting up a forward and a backward animation that could switch at any point? For example, if half way moving a mechanical arm in an animation, they need to go back a little bit because they went to far? And how do we control speed? Any links resources I can use to write this would be a huge help.
To help clarify my problem, here is the code that got the closest to what I was looking for:
using UnityEngine;
using System.Collections;
public class Control : MonoBehaviour {
public bool dragging;
public Vector2 mouseDownPoint;
public Vector2 mouseDragPoint;
public RaycastHit hit;
public float yDif;
public float animSpeed;
public Animator[] anims;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
//Determine if clicking over lever
if(Physics.Raycast(ray, out hit, 100f)){
if (Input.GetMouseButtonDown (0)) {
mouseDownPoint = new Vector2( Input.mousePosition.x / Screen.width , Input.mousePosition.y / Screen.height ) ;
}
else if(Input.GetMouseButtonUp(0)){
dragging = false;
}
}
//Keep calculating current mouse point
if (dragging) {
if(Input.GetMouseButton(0)){
mouseDragPoint = new Vector2( Input.mousePosition.x / Screen.width , Input.mousePosition.y / Screen.height ) ;
}
}
if(Input.GetMouseButtonUp(0)){
dragging = false;
}
GetYDifference();
}
void OnMouseDown(){// set the animators of the mechanical arm and the lever
dragging = true;
for (int i = 0; i < anims.Length; i++) {
anims[i].speed = 0f;
anims[i].SetTrigger("forward");
}
}
//Wanted to cap the distance needed to play animation at full speed
void GetYDifference(){
yDif = 0 + ( mouseDragPoint.y - mouseDownPoint.y);
if (yDif > 0) {
if (yDif > 0.25) {
animSpeed = 0.5f;
} else {
animSpeed = yDif * 2;
}
} else {
if (yDif < -0.25) {
animSpeed = -0.5f;
} else {
animSpeed = yDif * 2;
}
}
for (int i = 0; i < anims.Length; i++) {
anims[i].speed = animSpeed;
}
}
}
I’m sorry, I must not be understanding correctly. Are you saying this is a feature that will be built in with 5.1 and that there is no way to accomplish this now? There has to be a way to get close to that. I’ve reworked my code and this is what I have so far:
The gameobject is structed like this :
Empty Gameobject that holds the lever and has a good pivot point (this has the animator “lever”);
Lever object is a child with the scollider for the detection.
This works, but when if the drag is held down after the lever gets to the end point, when I reverse the animation its like it added frames it has to play through.
Example: If I drag up, the lever goes to the end of its animation (just a rotate to the end point). If I hold for an additional 1 second, when I drag down I have to wait one second before the animation plays in reverse. Any clue what is happening?
using UnityEngine;
using System.Collections;
public class LeverControl : MonoBehaviour {
public Vector2 mouseDownPoint;
public Vector2 mouseDragPoint;
public float yDif;
public float animSpeed;
private RaycastHit hit;
public bool dragging;
public Animator lever;
// Use this for initialization
void Start () {
lever.speed = 0;
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown (0)) {
Physics.Raycast( Camera.main.ScreenPointToRay( Input.mousePosition ), out hit, 1000f );
print(""+hit.collider.gameObject.tag);
if(hit.collider.gameObject.tag == "Lever"){
dragging = true;
mouseDownPoint = new Vector2( Input.mousePosition.x / Screen.width , Input.mousePosition.y / Screen.height ) ;
}
}
if (dragging) {
if(Input.GetMouseButton(0)){
mouseDragPoint = new Vector2( Input.mousePosition.x / Screen.width , Input.mousePosition.y / Screen.height ) ;
}
SetAnimSpeed();
}
if (Input.GetMouseButtonUp (0)) {
dragging = false;
}
}
void SetAnimSpeed(){
yDif = 0 + ( mouseDragPoint.y - mouseDownPoint.y);
animSpeed = yDif;
lever.speed = animSpeed;
}
}
I actually found a way that seems to work so far. Here is the new script:
using System.Collections;
public class LeverControl : MonoBehaviour {
public Vector2 mouseDownPoint;
public Vector2 mouseDragPoint;
public float yDif;
public float animSpeed;
private RaycastHit hit;
public bool dragging;
public bool atStart;
public bool atEnd;
public Animator lever;
// Use this for initialization
void Start () {
lever.speed = 0;
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown (0)) {
Physics.Raycast( Camera.main.ScreenPointToRay( Input.mousePosition ), out hit, 1000f );
print(""+hit.collider.gameObject.tag);
if(hit.collider.gameObject.tag == "Lever"){
dragging = true;
mouseDownPoint = new Vector2( Input.mousePosition.x / Screen.width , Input.mousePosition.y / Screen.height ) ;
}
}
if (dragging) {
if(Input.GetMouseButton(0)){
mouseDragPoint = new Vector2( Input.mousePosition.x / Screen.width , Input.mousePosition.y / Screen.height ) ;
}
SetAnimSpeed();
}
if (Input.GetMouseButtonUp (0)) {
dragging = false;
}
}
void SetAnimSpeed(){
yDif = 0 + ( mouseDragPoint.y - mouseDownPoint.y);
if (yDif > 0 && atEnd == true) {
yDif = 0;
} else if (yDif < 0 && atStart == true){
yDif = 0;
}
lever.speed = yDif;
}
public void SetEnd(int end){
if (end == 0) {
atStart = true;
atEnd = false;
} else if (end == 1) {
atStart = false;
atEnd = true;
} else {
atStart = false;
atEnd = false;
}
}
}
On the second frame I put the parameter at 0 and the third frame has one at 2. At the tail end the third to last has one at 2, and the second to last has one set at 1. This stops the animation from trying to pass a certain point after the animation ends.
If there is a better way I am all ears, but this SEEMS to be working at the moment. If this is an upcoming feature I look forward to it
(this so far is only for the lever, but the same should work elsewhere too)
I suppect that your clip is not loop time, when you play past the end of the clip the time continue to increment at each evaluation, if you hold the lever for an additionnal 1 second after the end of the clip the state time is now ‘stop time + 1’
that why you have to wait 1 second, state time need to be in the animation range to see anything animated. You could potentially use Animator.Play to rewind the clip in the animation range of the clip