【游戏开发实战】TapTap物理画线游戏,教你使用Unity实现2D物理画线功能,看到我为你画的彩虹了吗
文章目錄
- 一、前言
- 二、思考
- 三、驗證我們的思考
- 1、創(chuàng)建物體掛組件
- 2、設(shè)置組件參數(shù)
- 3、運行測試
- 4、結(jié)論
- 四、擼起袖子寫代碼
- 1、Line.cs
- 2、LinesDrawer.cs
- 五、場景
- 六、最終運行效果
一、前言
嗨,大家好,我是新發(fā),我又來科普了,相信很多人玩過物理畫線小游戲,比如下面這樣子:
使用Unity如何實現(xiàn)物理畫線功能呢?今天就來教大家。
最后的實現(xiàn)效果如下:
本工程已上傳到GitHub,感興趣的同學可自行下載學習。
GitHub地址:https://github.com/linxinfa/UnityPhysicsDrawLine
二、思考
物理畫線的核心就是:物理+畫線。
物理:
想要有物理特性,最簡單的做法就是掛碰撞體(Collider)和剛體(Rigidbody)組件。
畫線:
可以使用LineRenderer組件來實現(xiàn)畫線功能。
三、驗證我們的思考
1、創(chuàng)建物體掛組件
創(chuàng)建一個空物體,重命名為Line,掛上EdgeCollider2D、Rigidbody2D和LineRenderer組件。
2、設(shè)置組件參數(shù)
設(shè)置一下LineRenderer組件的參數(shù)。
Position:坐標點;
Width:線寬度;
Color:線顏色(支持漸變);
Corner Vertices:拐彎處的頂點數(shù)量(讓拐彎圓滑一點);
End Cap Vertices:線段頭尾的頂點數(shù)量(讓線段頭尾圓滑一點);
Use World Space:是否使用世界坐標(不要勾選);
Materias:材質(zhì)球。
設(shè)置一下EdgeCollider2D組件的參數(shù)。
Edge Radius:邊界碰撞體的半徑。
Points:邊界碰撞體的坐標點(要與LineRenderer的點一致)。
邊界碰撞體設(shè)置完之后效果如下:
最后是Rigidbody2D組件的參數(shù)。主要是Gravity Scale:重力縮放值;這個值越大,物體受到的重力越大,掉落的加速度就越大。
3、運行測試
為了模擬掉落到地上的效果,我們加個地面。
運行測試效果如下:
4、結(jié)論
理論存在,實踐驗證成功。那么,接下來就是如何使用代碼來實現(xiàn)鼠標畫線了,關(guān)鍵的點就是把鼠標的坐標設(shè)置為線的點。
四、擼起袖子寫代碼
兩個腳本,一個Line.cs負責線段的繪制,一個LinesDrawer.cs負責檢測鼠標和生成線段與點。
1、Line.cs
using System.Collections; using System.Collections.Generic; using UnityEngine;/// <summary> /// 線腳本 /// </summary> public class Line : MonoBehaviour {public LineRenderer lineRenderer;public EdgeCollider2D edgeCollider;public Rigidbody2D rigidBody;/// <summary>/// 點數(shù)組/// </summary>[HideInInspector] public List<Vector2> points = new List<Vector2>();[HideInInspector] public int pointCount = 0;/// <summary>/// 畫線過程中點與點的最小距離/// </summary>float pointsMinDistance = 0.1f;float circleColliderRadius;/// <summary>/// 添加點/// </summary>/// <param name="newPoint"></param>public void AddPoint(Vector2 newPoint){if (pointCount >= 1 && Vector2.Distance(newPoint, GetLastPoint()) < pointsMinDistance)return;points.Add(newPoint);++pointCount;// 添加圓形碰撞var circleCollider = this.gameObject.AddComponent<CircleCollider2D>();circleCollider.offset = newPoint;circleCollider.radius = circleColliderRadius;// Line RendererlineRenderer.positionCount = pointCount;lineRenderer.SetPosition(pointCount - 1, newPoint);// 邊界碰撞體的點if (pointCount > 1)edgeCollider.points = points.ToArray();}/// <summary>/// 獲取最后一個點/// </summary>/// <returns></returns>public Vector2 GetLastPoint(){return lineRenderer.GetPosition(pointCount - 1);}/// <summary>/// 是否啟用物理特性/// </summary>public void UsePhysics(bool usePhysics){rigidBody.isKinematic = !usePhysics;}/// <summary>/// 設(shè)置線顏色/// </summary>/// <param name="colorGradient"></param>public void SetLineColor(Gradient colorGradient){lineRenderer.colorGradient = colorGradient;}/// <summary>/// 設(shè)置畫線的點與點之間的最小距離/// </summary>/// <param name="distance"></param>public void SetPointsMinDistance(float distance){pointsMinDistance = distance;}/// <summary>/// 設(shè)置線寬度/// </summary>/// <param name="width"></param>public void SetLineWidth(float width){lineRenderer.startWidth = width;lineRenderer.endWidth = width;circleColliderRadius = width / 2f;edgeCollider.edgeRadius = circleColliderRadius;} }2、LinesDrawer.cs
using UnityEngine;/// <summary> /// 畫線控制器 /// </summary> public class LinesDrawer : MonoBehaviour {public GameObject linePrefab;public LayerMask cantDrawOverLayer;int cantDrawOverLayerIndex;[Space(30)]public Gradient lineColor;public float linePointsMinDistance;public float lineWidth;Line currentLine;Camera cam;private void Start(){cam = Camera.main;cantDrawOverLayerIndex = LayerMask.NameToLayer("CantDrawOver");}private void Update(){if (Input.GetMouseButtonDown(0))BeginDraw();if (null != currentLine)Draw();if (Input.GetMouseButtonUp(0))EndDraw();}// 畫線邏輯-----------------------------------------------------------------------// 開始畫線void BeginDraw(){// 實例化線預(yù)設(shè)currentLine = Instantiate(linePrefab, this.transform).GetComponent<Line>();// 設(shè)置參數(shù)currentLine.UsePhysics(false);currentLine.SetLineColor(lineColor);currentLine.SetPointsMinDistance(linePointsMinDistance);currentLine.SetLineWidth(lineWidth);}// 畫線進行中void Draw(){var pos = cam.ScreenToWorldPoint(Input.mousePosition);// 防止線與線之間交叉RaycastHit2D hit = Physics2D.CircleCast(pos, lineWidth / 3f, Vector2.zero, 1f, cantDrawOverLayer);if (hit)EndDraw();elsecurrentLine.AddPoint(pos);}// 畫線結(jié)束void EndDraw(){if (null == currentLine) return;if (currentLine.pointCount < 2){Destroy(currentLine.gameObject);}else{currentLine.gameObject.layer = cantDrawOverLayerIndex;currentLine.UsePhysics(true);currentLine = null;}} }五、場景
將原來的Line保存為預(yù)設(shè),并掛上Line腳本,賦值對應(yīng)的變量。
添加一個Layer:CantDrawOver,目的是防止畫線的時候線與線交叉(也可以防止線與其他被標記為CantDrawOver層的物體交叉)。
在場景中創(chuàng)建一個空物體,重命名為LineDrawer,并掛上LineDrawer腳本,賦值對應(yīng)的參數(shù)。
六、最終運行效果
總結(jié)
以上是生活随笔為你收集整理的【游戏开发实战】TapTap物理画线游戏,教你使用Unity实现2D物理画线功能,看到我为你画的彩虹了吗的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 推荐个东西,GPGPU开发
- 下一篇: 《编码:隐匿在计算机软硬件背后的语言》T