Hi there, I need some help with smoothing my lookat. Because it turns direct to the target. Can I somehow smooth it or use something else? That you can really see it turn. ~Glemau
Multiple ways to achieve this. One would be: Code (csharp): // in your Update function transform.rotation = Quaternion.RotateTowards ( transform.rotation, Quaternion.LookRotation( transform.position - target.position ), Time.deltaTime * yourTurnRate ); Generally look at Lerp and other functions.
This thread is kind of old, but might be helpful for someone else. If you need to rotate and fire at the end of rotation - do rotation in coroutine: Code (CSharp): <...> StopCoroutine("RotateToFire"); StartCoroutine(RotateToFire(hit)); <...> IEnumerator RotateToFire(Vector3 hitPoint) { //transform.LookAt(hitPoint); Vector3 dir = (hitPoint - transform.position).normalized; Quaternion rotTo = Quaternion.LookRotation(dir); while(true) { transform.rotation = Quaternion.RotateTowards( transform.rotation, rotTo, Time.deltaTime * turnSpeedToFire); if(Vector3.Angle(transform.forward, dir) < 1) break; yield return null; } // fire // ... }
funny guy. Seriously, why "abusing co-routines"? Is there any problems by using them? It is a good practice to put in coroutines a code that does not need to be executed in every single frame, even docs are pointing that out. In my example, you turn, fire, and wait. No performance hit. The same exact way many tweens work when you schedule something. Also, if you would look closely there was an error in the first suggested code: "transform.position - target.position" - that gives an opposite direction. It should be "target.position - transform.position".
I'm also curious what's wrong with that coroutine? I use them for similar functionality all the time. I use them to death.
Co-routines are meant to be used when you have something you would like to run repeatedly for long periods of time. The given example by dpolyakov is abusing them because it returns the moment rotation ends. The co-routine will then have to be restarted every single time you want to rotate your object. You are allocating extra garbage for the GC(which will now also run more often) to collect and creating unnecessary overhead with the method calls. P.S. The documentation needs to be changed to highlight the "dangers" of using co-routines for small tasks.
> "Co-routines are meant to be used when you have something you would like to run repeatedly for long periods of time." Sure, why not? "long period of time" is a relative measurement. It can be a fraction of a second or longer than a minute. AFAIK, the whole idea of co-routines is to off load a code from Update(). When you use "yield return null" - it is executed in every single frame and yes there is an "overhead" of a few ticks (really??? you would worry about that?). But once, let's say, gun's rotation is ended, why to call this rotation again? Of cause you can put it all in Update and use flags to check what to call, or you can use co-routines that were designed for that. Performance wise - it depends on what you are doing. Issuing thousands of co-routines at the same time will surely drop FPS. For few hundreds - there is no performance hit you will notice at all. If you are fighting for every single tick of your precious CPU time - do not use co-routines. For me, I prefer to actually program logic in the most convenient way, make sure that it works as designed, and worry about performance later _IF_ I hit some slowdowns. More likely, it will be somewhere else, like graphics related than some co-routine.
http://forum.unity3d.com/threads/why-do-people-hate-coroutines.260160/page-3#post-1722915 I will just put this here for you to read as I do not wish to re-iterate all the reasons co-routines are bad. You could just as easily disable/enable the rotator component without the overhead produced from a co-routine. Your components should at the very least try to follow the single responsibility principle(https://drive.google.com/file/d/0ByOwmqah_nuGNHEtcU5OekdDMkk/view?pref=2&pli=1).
Code (CSharp): using UnityEngine; using System.Collections; public class LookAtTarget : MonoBehaviour { public Transform target; public Vector2 rotRange; public bool smoothRot; public float followDelay = 1; Vector3 followAngles; Vector3 refVelocity; Vector3 localTarget,targetAngles; float yAngle,xAngle; void Update() { if(target!=null) { transform.localRotation=Quaternion.identity; localTarget = transform.InverseTransformPoint(target.position); yAngle = Mathf.Atan2(localTarget.x, localTarget.z)*Mathf.Rad2Deg; yAngle = Mathf.Clamp(yAngle, -rotRange.y*.5f, rotRange.y*.5f); transform.localRotation=Quaternion.Euler(0,yAngle,0); localTarget = transform.InverseTransformPoint(target.position); xAngle = Mathf.Atan2(localTarget.y, localTarget.z)*Mathf.Rad2Deg; xAngle = Mathf.Clamp(xAngle, -rotRange.x*.5f, rotRange.x*.5f); if(smoothRot) { targetAngles = new Vector3(followAngles.x + Mathf.DeltaAngle(followAngles.x, xAngle), followAngles.y + Mathf.DeltaAngle(followAngles.y, yAngle)); followAngles = Vector3.SmoothDamp(followAngles, targetAngles, ref refVelocity, followDelay); transform.localRotation = Quaternion.Euler(-followAngles.x, followAngles.y, 0); } else { targetAngles=new Vector3(xAngle,yAngle); transform.localRotation = Quaternion.Euler(-targetAngles.x, targetAngles.y, 0); } } } }
Well, it this case I prefer my own opinion based on my experience and work. Here, co-routines help me to achieve what I need. I'm not fighting for the cleanest code or extra tick (I'm sure that I can point out a lot of stuff in your yard). I reach goals - functionality that I need, not how my "pretty" code is evaluated by some random dude on the Internet. If you prefer to spend all your time optimizing code and reading on forums that something that is btw offered by language and (in this case) engine is bad because some other random guy cannot understand it, lol, go ahead!
Do you mean there are GC allocations each time a coroutine is started? Do you have some references about this?
There is an allocation. All coroutines are built on top of C# yield keyword. Actually, it is a very clever implementation that simulates multi-threading without needing synchronization methods. So there are some little allocations to keep references. Also there is an allocation when you do WaitForSeconds. GC - will need to release a little bit more as well. But all these allocations are very small. Nothing to worry about. You can argue that a statement Vector v = new Vector(x, y, z) will have an impact on your performance, but there is no way you can feel it, unless you make a synthetic test to prove the point, but who really cares that on million allocations it will take 0.1sec?
I don't know what everyone is screaming about but this makes your transform look at an object and staying in the upright direction. Code (CSharp): Quaternion direction =Quaternion.LookRotation(target.position-transform.position, transform.TransformDirection(Vector3.up)); transform.rotation = Quaternion.Lerp(transform.rotation, direction, Time.deltaTime*rotateSpeed);
@dpolyakov Well, if there are GC allocations, even if they are very small, that's not to be ignored. It could have a performance issue since it can trigger the GC more often. I understood that's particularly noticeable on mobile platforms, thought I have not run tests myself to benchmark that.