SteamVR Parabolic Movement
In fact, the implementation of the parabolic is very simple, generate a set of parabolic points, and then render the point into a line just fine. There are many ways to render a line, you can use a model, or you can use GL to draw segments, or you can use linerender. The focus is on the generation and calculation of the optimization points.
Landlord to work relatively busy, rarely write demo. I do projects generally have a strict framework, but in order to more concise display of the implementation of the function of a lot of code, and write a code that does not conform to my style, is to let everyone see clearly the implementation of the function.
I am not a personal developer, there is no test environment in the home, if there is a problem can reply below. The code in this tutorial has been used in the actual case, because the work is confidential I can not or share the project source code, just the development process of the part of the function to share in personal name, welcome to Exchange.
How to generate parabolic points, a very simple formula:
Nextpos = Lastpos + Horizontal Displacement + vertical displacement.
I'm not going to go into the details of a later code with detailed comments.
The focus is on the optimization of the point set, the optimization of the parabolic point two parts, one is how to calculate the collision point, and the second is the memory cost optimization. Considering that the general VR Project only moves on the horizontal plane, the collision is judged by judging the y-axis of the parabolic point . With regard to memory overhead, we can limit the number of generated parabolic points while optimizing calculations. We use a List to save point sets, dynamically generate points based on point conditions, or change the position of points. For example, when the handle angle is constant, just Change the point in the list collection to the Y -axis.
Now the idea is clear. Here is the pseudo-code:
int i = 0;
while (nextpos.y>0 && maxpoint>0) {
if (list.count<=i) {
List.add (Nextpos);
}
else{
List[i] = Nextpos;
}
generate, optimize, calculate the next parabolic point
i++;
}
List.remove (i,list.count-i);// Remove excess data from the previous point set
After creating the parabolic point set, the next step is to draw the curve,linerender,GL can be easily drawn. But in terms of performance, GL is a bit faster. We recommend that you use GL. Of course, you can also use your own model to draw, the principle is to generate your model at the corresponding point, and then calculate the corresponding angle. These implementation scenarios I will write in the code, the effect of the call to see themselves.
The end is to generate the end of the parabola, because I am in accordance with the y - axis to determine the placement of the parabolic, but there may be obstacles and so on, or landing in the corner, these positions are obviously not jumping, so we need to determine the landing point. In Physics There is a way to detect whether a spherical range will collide, we can add a layer to the ground to ignore the ground detection, so that we can safely land.
Well, maybe you don't understand, it's okay, next is the code, and the code has a detailed comment.
Using unityengine;using system.collections.generic;using system;///<summary>///parabola script//</summary> public class handray:monobehaviour{Private Transform currenthand;//The Hand of the current trigger private list<vector3> pointlist; Curve point set private quaternion lastrotation; The previous moving angle private Vector3 lastpostion; Previous location private Vector3 Lastpos; Last point, in order to optimize a temporary variable into a global, save memory overhead private Vector3 nextpos;//The next point, for the same reason as the private event Action onchangetransform;//an event that is used to check Measuring the position and angle of the handle changes the private Material material;//the material of the rendered Ray ball private Vector3 hitpoint;//parabolic collision point private Ray Ray; private bool Canjump = false;//public gameobject pointeffect;//A special effect, is to place a beam of light at the end of the ray or something, you can do this special effect public int Maxpoi nt The maximum number of points to generate a curve public float distence;//horizontal displacement public float grity;//vertical displacement public float checkrange;//detect position presence Barrier Publ IC void Awake () {SetData (); } public void Start () {pointlist = new list<vector3> (); Onchangetransform + = OnchangetranSformcallback; HitPoint =-vector3.one; Ray = new Ray (); The public void Update () {/////When the handle presses the touch key while the angle is appropriate, the trigger event starts the compute point if (currenthand! = null && (CURRENTHAND.E Ulerangles.x > 275 && currenthand.eulerangles.x <= 360) | | (currenthand.eulerangles.x >= -0.01f && currenthand.eulerangles.x < 85))) {if (onchangetransform! = null) onchangetransform (); } else {pointlist.clear (); Pointeffect.setactive (FALSE); Nsformcallback () {if (lastrotation! = Currenthand.rotation | | lastpostion! = currenthand.position) { Lastpos = Nextpos = currenthand.position; int i = 0; while (Nextpos.y > 0 && (I < maxpoint)) {if (Pointlist.count <= i) { Pointlist.add (Nextpos); } else {pointlist[i] = Nextpos; } if (lastrotation = = Currenthand.rotation && lastpostion! = currenthand.position && i < pointlist.count-1) {Nextpos = Pointlist[i + 1] + currenthand.position-lastpostion; } else {Nextpos = Lastpos + currenthand.rotation * vecto R3.forward * distence + vector3.up * grity * 0.1f * i * time.fixeddeltatime; } Lastpos = Nextpos; i++; } if (Pointlist.count > i) {pointlist.removerange (I, pointlist.count-i); } lastrotation = Currenthand.rotation; Lastpostion = currenthand.position; if (Pointlist.count > 1) {HitPoint = Pointlist[pointlist.count-1]; Pointeffect.setactive (TRUE); PointEffect.transform.position = HitPoint; } else {HitPoint =-vector3.one; Pointeffect.setactive (FALSE); }}} public void Enable () {SteamVR_InitManager.Instance.OnLeftDeviceActive + = onhandactive; SteamVR_InitManager.Instance.OnRightDeviceActive + = onhandactive; Onchangetransform + = Onchangetransformcallback; public void onhandactive (Steamvr_trackedobject obj) {deviceinput device = obj. Getcomponent<deviceinput> (); Device. OnPressDownPadV3 + = Onpressdownpad; Device. Onpressuppad + = onpressuppadaction; } public void Onhanddis (Steamvr_trackedobject obj) {if (obj && obj.gameObject.activeSelf) { Deviceinput device = obj. Getcomponent<deviceinput> (); Device. OnPressDownPadV3-= Onpressdownpad; Device. OnpressuppAd-= onpressuppadaction; }} public void Disable () {SteamVR_InitManager.Instance.OnLeftDeviceActive-= onhandactive; SteamVR_InitManager.Instance.OnRightDeviceActive-= onhandactive; Onhanddis (SteamVR_InitManager.Instance.LeftObject); Onhanddis (SteamVR_InitManager.Instance.LeftObject); Onchangetransform-= Onchangetransformcallback; public void SetData () {if (Pointeffect) pointeffect.setactive (false); }///<summary>///When lifting the touchpad, the calculation is based on//</summary> private void Onpressuppadaction () {if ( Currenthand = = null) return; Canjump = true; Ray.origin = currenthand.position; Vector3 dir = hitpoint-currenthand.position; Ray.direction = dir; if (Physics.checksphere (HitPoint, Checkrange, ~ (1 << 8))) {canjump = false; } if (Canjump) {jumppoint (HitPoint); } Currenthand = nulL }///<summary>///skip to specified points///</summary>//<param name= "point" ></param> public V OID Jumppoint (Vector3 point) {point.y = TRANSFORM.POSITION.Y; Transform.position = point; } private void Onpressdownpad (Transform parent) {Currenthand = parent; }///<summary>///Use GL to draw curves///Draw points out///</summary> void Onrenderobject () {Mater Ial. SetPass (0); if (pointlist = = null) return; Gl. Begin (GL. LINES); for (int i = 0; i < Pointlist.count; i++) {GL. Vertex (Pointlist[i]); } GL. End (); }///<summary>///////An additional method of drawing a parabola with a curve, which is less performance because the points are more than///interested in adding this method to update///</summary> public void Showlinebyrender () {Linerenderer line = getcomponent<linerenderer> (); if (line) {line. Setvertexcount (Pointlist.count); for (int i = 0; i < pointlist.cOunt; i++) {line. SetPosition (i, pointlist[i]); } } }}
Use of Steam VR (ii)