unity编程——小玩具

今天做了一个萤火虫飞舞效果,这个问题类似于一道算法题:一个点想移动到平面上任意一点,但是自身有一个旋转角度限制,每一次旋转时,最大旋转角度是 maxRotateAngle,思维延时(即两次连续执行自身指令的间隔)是 float gap。

大致思路是:

建立了四个指令,分别是:

Blink()—— 萤火虫屁股发光,是闪烁的......闪烁的...

Move()——(默认使用 Vector2 curSpeed 作为移动增量)

ComputeDir() —— 根据目标位置,计算当前运动方向,因为旋转角度限制无法一次直达。

Escape()—— 这个纯属自娱自乐了,哈哈,当鼠标接近萤火虫时,他就会“拼命地”逃离鼠标,我自己瞎搞的玩的。

 

unity编程——小玩具

这里只加了一直萤火虫,可以加更多。

(美术实在太差,,,凑合看看热闹吧....)

*******************************************************

技术细节:

1.转向问题有点棘手,因为要考虑很多方面。其中之一就是坐标系问题我在这个脚本里面用了Graphics.DrawTexture()函数,这个底层函数的坐标原点和其他的不太一样,是左上角为原点的。

如果不熟悉,可以用 print() 多测试几次,我就是这么搞的。(>_<)。

(改了好几次,写了好多个版本。最终敲定了现在手上的版本。)

2.其二考虑的是效率问题了,转向,三角函数是少不了用的,其中我想到了的一种方法以萤火虫自身为原点,前进方向为Y轴建立坐标系,然后进行计算。这个法子很笨的,因为后期还要把目标点切出来转换到屏幕空间,反而繁琐了;也许是我能力不够,没找到优化方法吧。

我所采用的方法是,直接在屏幕空间来进行计算。因为有了统一他标准,少了很多转换,优化手段也多了起来。具体来说也很繁琐。

优化无止境啊... 大概思路还是那句老话:用更少的空间代价,换取更快的速度。

3.说一说Graphics绘图:用过了几次后,(发现这个有点类似于Java的绘图,JAVA绘图很简单,应该说实际上不止JAVA各个绘图API底层都是这样的语法。)

这个底层绘图不能随便用,因为深度测试绕过去了,绘制顺序必须再自己统一规定,不利于模块化;

它的使用有一些点必须注意:

 unity编程——小玩具

必须是这样的格式,在发生repaint 时才能绘制。联系JAVA、win32的知识,就知道了repaint,这绝对是在最后一个绘制的,前面的深度测试,顶点变换什么的他都不干,直接插队到最后,就是这样一个霸道的站在世界的顶点的男银。

————————————————————————————————————————————————

最后一环,贴代码吧:

 自己写的也有很多不足,模块化不像模块化,函数之间的接替性不够,因为是我自己一个人玩玩,所以能用全局变量全部用的全局变量。还有很多,希望童鞋们不吝指教,多多与我交流,^_^

 

  1 using UnityEngine;

  2 using System.Collections;

  3 

  4 public class Star : MonoBehaviour {

  5 

  6     public Vector2 initPosPercent;

  7 

  8     public float maxComputeDestGap = 1.0f;

  9     public float curComputeDestGap = 0.0f;

 10     public float computeDirGap = 0.5f;

 11     public float curComputeDirTime = 0.0f;

 12     // 纹理

 13     public Texture2D starBgd;

 14     private Rect bgdRT = new Rect(0,0,0,0);

 15     float maxWidth, maxHeight, width, height;

 16 

 17     // 图片宽

 18     public float percentWidth = 0.1f;

 19 

 20     // 速度最大值

 21     public float maxSpeedAmount = 0.2f;

 22 

 23     // 当期速度值

 24     public float curSpeedAmount = 0.2f;

 25 

 26     // 放大种子

 27     public float scaleSeed = 0.0f;    // 初始扩大系数

 28     public float maxScale = 0.8f, minScale = 0.5f;

 29 

 30     // 最大旋转角度

 31     public float maxRotateAngle = 0.5f;    // 大约30度

 32     float curRotateAngle = 0.0f;

 33     // 当前速度

 34     private Vector2 curSpeed = new Vector2(0.0f,0.0f);

 35     // 当前缩放比

 36     private float curScale = 1.0f;

 37 

 38     private float destX = 0.0f, destY = 0.0f;

 39 

 40     // 常量

 41     private float halfPI;

 42     private float PI2;

 43 

 44     // 逃跑警戒距离

 45     public float escapeDist;

 46     public float escapeSpeedAmount;

 47 

 48     // Use this for initialization

 49     void Start () {

 50 

 51         Vector3 pos = new Vector3 (Screen.width * initPosPercent.x, Screen.height * initPosPercent.y, 0.0f);

 52         transform.position = pos;

 53 

 54         width = maxWidth = Screen.width * percentWidth;

 55         height = maxHeight = width;

 56 

 57         bgdRT = new Rect ( transform.position.x, transform.position.y, width*curScale, height*curScale );

 58 

 59 

 60         halfPI = Mathf.PI * 0.5f;

 61         PI2 = Mathf.PI * 2.0f;

 62     }

 63     

 64 

 65     // Update is called once per frame

 66     void Update () {

 67 

 68         if (curComputeDestGap < maxComputeDestGap )

 69             curComputeDestGap += Time.deltaTime;

 70         else

 71         {

 72             // 生成新目标

 73             destX = Random.Range (0, Screen.width);

 74             destY = Random.Range (0, Screen.height);

 75 

 76             curComputeDestGap = 0.0f;

 77         }

 78 

 79         if (curComputeDirTime < computeDirGap )

 80             curComputeDirTime += Time.deltaTime;

 81         else

 82         {

 83             // 生成新方向

 84             ComputeDir ( destX, destY);

 85             

 86             curComputeDirTime = 0.0f;

 87         }

 88 

 89 

 90         // 逃离

 91         Escape ();

 92 

 93         // 移动 star 

 94         Move ();

 95 

 96     }

 97 

 98 

 99     void OnGUI()

100     {

101         if( Event.current.type.Equals(EventType.Repaint) )

102         {

103             //    print ( x );

104             float x = transform.position.x - width * 0.5f;

105             float y = transform.position.y - height * 0.5f;

106             bgdRT = new Rect ( x, y, width, height );

107 

108 

109             GUI.DrawTexture ( bgdRT, starBgd );

110         }

111     }

112 

113     void Blink()

114     {

115         curScale = (maxScale - minScale)* 0.5f * Mathf.Sin (Time.time + scaleSeed) + maxScale;

116         

117         width = maxWidth * curScale;

118         height = width;

119     }

120 

121     void Escape()

122     {

123         Vector2 pos = new Vector2 ( transform.position.x, transform.position.y );

124         Vector2 mousePos = new Vector2 ( 0, 0 );

125         mousePos.x = Input.mousePosition.x;

126         mousePos.y = Screen.height - Input.mousePosition.y;

127 

128         float dist = Vector2.Distance ( mousePos, pos);

129 

130         if( dist <= escapeDist )

131         {

132             Vector2 dir = new Vector2( 0.0f, 0.0f );

133 

134             dir = pos - mousePos;

135 

136             dir.Normalize();

137             curSpeed = dir * escapeSpeedAmount;

138         }

139     }

140 

141 

142     void Move ()

143     {

144         float t = transform.position.x + curSpeed.x;

145 

146         // 防越界

147         if ( t < 0.0f || t > Screen.width )

148             curSpeed.x = -curSpeed.x;

149         t = transform.position.y + curSpeed.y;

150         if (t < 0.0f || t > Screen.height)

151             curSpeed.y = -curSpeed.y;

152         

153         

154         transform.Translate ( curSpeed.x * Time.deltaTime, curSpeed.y*Time.deltaTime, 0);

155     }

156 

157     void ComputeDir( float srcX, float srcY )

158     {

159         // 根据源位置计算目标位置,旋转角度有限所致

160         float m = srcX - transform.position.x;

161         float n = srcY - transform.position.y;

162 

163         // 在自身坐标系中的坐标

164         float angle = Mathf.Atan2 ( n, m );

165 

166         float dAngle = angle - curRotateAngle;

167 

168         // 转变成 pi < A - C < -PI

169         if (dAngle < -Mathf.PI) {

170             angle += PI2;

171         }

172         else if( dAngle > Mathf.PI )

173         {

174             angle -= PI2;

175         }

176 

177         dAngle = angle - curRotateAngle;

178 

179 

180         // 计算最终角度

181         if (dAngle > -maxRotateAngle && dAngle < maxRotateAngle)

182         {

183             // 一步即达的目标方向

184             curRotateAngle = angle;

185         }

186         else

187         {

188             if( dAngle < 0.0f )

189             {

190                 curRotateAngle -= maxRotateAngle;

191             }

192             else

193             {

194                 curRotateAngle += maxRotateAngle;

195             }

196 

197         }

198 

199         // 转换到 -PI 到 PI 空间

200         if (curRotateAngle < -Mathf.PI) {

201             curRotateAngle += PI2;

202         }

203         else if( curRotateAngle > Mathf.PI )

204         {

205             curRotateAngle -= PI2;

206         }

207 

208         // 计算最终速度

209         curSpeed.x = curSpeedAmount * Mathf.Cos ( curRotateAngle );

210         curSpeed.y = curSpeedAmount * Mathf.Sin ( curRotateAngle );

211 

212         return;

213     }

214     

215 }

 

 ***************

吐硼:

 C#真是够了,虐的我压灭压灭的,一说全是泪啊....

 

你可能感兴趣的:(unity)