文章目录

  • 一、前言
  • 二、思考
  • 三、验证我们的思考
    • 1、创建物体挂组件
    • 2、设置组件参数
    • 3、运行测试
    • 4、结论
  • 四、撸起袖子写代码
    • 1、Line.cs
    • 2、LinesDrawer.cs
  • 五、场景
  • 六、最终运行效果

一、前言

嗨,大家好,我是新发,我又来科普了,相信很多人玩过物理画线小游戏,比如下面这样子:

使用Unity如何实现物理画线功能呢?今天就来教大家。

最后的实现效果如下:

本工程已上传到GitHub,感兴趣的同学可自行下载学习。
GitHub地址:https://github.com/linxinfa/UnityPhysicsDrawLine

二、思考

物理画线的核心就是:物理+画线。
物理:
想要有物理特性,最简单的做法就是挂碰撞体(Collider)和刚体(Rigidbody)组件。
画线:
可以使用LineRenderer组件来实现画线功能。

三、验证我们的思考

1、创建物体挂组件

创建一个空物体,重命名为Line,挂上EdgeCollider2DRigidbody2DLineRenderer组件。

2、设置组件参数

设置一下LineRenderer组件的参数。
Position:坐标点;
Width:线宽度;
Color:线颜色(支持渐变);
Corner Vertices:拐弯处的顶点数量(让拐弯圆滑一点);
End Cap Vertices:线段头尾的顶点数量(让线段头尾圆滑一点);
Use World Space:是否使用世界坐标(不要勾选);
Materias:材质球。

设置一下EdgeCollider2D组件的参数。
Edge Radius:边界碰撞体的半径。
Points:边界碰撞体的坐标点(要与LineRenderer的点一致)。

边界碰撞体设置完之后效果如下:

最后是Rigidbody2D组件的参数。主要是Gravity Scale:重力缩放值;这个值越大,物体受到的重力越大,掉落的加速度就越大。

3、运行测试

为了模拟掉落到地上的效果,我们加个地面。

运行测试效果如下:

4、结论

理论存在,实践验证成功。那么,接下来就是如何使用代码来实现鼠标画线了,关键的点就是把鼠标的坐标设置为线的点。

四、撸起袖子写代码

两个脚本,一个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>/// 点数组/// </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>/// 设置线颜色/// </summary>/// <param name="colorGradient"></param>public void SetLineColor(Gradient colorGradient){lineRenderer.colorGradient = colorGradient;}/// <summary>/// 设置画线的点与点之间的最小距离/// </summary>/// <param name="distance"></param>public void SetPointsMinDistance(float distance){pointsMinDistance = distance;}/// <summary>/// 设置线宽度/// </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(){// 实例化线预设currentLine = Instantiate(linePrefab, this.transform).GetComponent<Line>();// 设置参数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);}// 画线结束void EndDraw(){if (null == currentLine) return;if (currentLine.pointCount < 2){Destroy(currentLine.gameObject);}else{currentLine.gameObject.layer = cantDrawOverLayerIndex;currentLine.UsePhysics(true);currentLine = null;}}
}

五、场景

将原来的Line保存为预设,并挂上Line脚本,赋值对应的变量。

添加一个LayerCantDrawOver,目的是防止画线的时候线与线交叉(也可以防止线与其他被标记为CantDrawOver层的物体交叉)。

在场景中创建一个空物体,重命名为LineDrawer,并挂上LineDrawer脚本,赋值对应的参数。

六、最终运行效果

【游戏开发实战】TapTap物理画线游戏,教你使用Unity实现2D物理画线功能,看到我为你画的彩虹了吗相关推荐

  1. HTML5 Canvas游戏开发实战 PDF扫描版

    HTML5 Canvas游戏开发实战主要讲解使用HTML5 Canvas来开发和设计各类常见游戏的思路和技巧,在介绍HTML5 Canvas相关特性的同时,还通过游戏开发实例深入剖析了其内在原理,让读 ...

  2. HTML5游戏开发实战

    <HTML5游戏开发实战> 基本信息 原书名:HTML5 Games Development by Example: Beginner's Guide 作者: (美)Makzan 译者: ...

  3. 游戏开发实战之弹球游戏

    文/Steffen Itterheim.Andreas Löw 为了更好地使用Box2D物理引擎,本文我们将制作一个真实的弹球游戏.弹球游戏桌利用各种物理世界的效果来创造有趣的体验.然而,在使用物理引 ...

  4. 《HTML5 Canvas游戏开发实战》——2.1 绘制基本图形

    本节书摘来自华章计算机<HTML5 Canvas游戏开发实战>一书中的第2章,第2.1节,作者:张路斌著, 更多章节内容可以访问云栖社区"华章计算机"公众号查看. 2. ...

  5. 从踩坑到填坑|淘宝Web 3D应用与游戏开发实战

    导读:本文是淘宝前端技术专家--徐乾伟(烧鹅)分享的淘宝 Web 3D 应用与游戏开发实战,这个话题在业界被谈及得比较少.今天将会从移动.3D.游戏三种交叉的话题来和大家探讨.接下来和小编一起从初试 ...

  6. 【游戏开发实战】Unity手游第一人称视角,双摇杆控制,FPS射击游戏Demo(教程 | 含Demo工程源码)

    文章目录 一.前言 二.实现方案 1.无主之地,第一人称视角 2.我之前做的摇杆控制 3.第一人称视角 + 摇杆控制 三.开始实战 1.资源获取:Unity AssetStore 2.Low Poly ...

  7. 《Unity 5.x游戏开发实战》一1.9 添加一个水平面

    本节书摘来异步社区<Unity 5.x游戏开发实战>一书中的第1章,第1.9节,作者: Alan Thorn 译者: 李华峰 责编: 胡俊英,更多章节内容可以访问云栖社区"异步社 ...

  8. 【游戏开发实战】用Go语言写一个服务器,实现与Unity客户端通信(Golang | Unity | Socket | 通信 | 教程 | 附工程源码)

    文章目录 一.前言 二.Go开发环境搭建(Windows系统) 1.安装Go命令行工具 2.创建GoWorkspace目录 3.配置GOPATH环境变量 4.配置GOPROXY代理 5.安装VSCod ...

  9. 《Unity 2D与3D手机游戏开发实战》简介

    #好书推荐##好书奇遇季#<Unity 2D与3D手机游戏开发实战>,京东当当天猫都有发售.彩色印制,定价89元,网店打折销售更便宜.本书配套源码.PPT课件,适合Unity游戏开发初学者 ...

最新文章

  1. UE5蓝图初学课程 Unreal Engine 5: Blueprints for Beginners
  2. java直接打开word_Java
  3. java final修饰符_java final修饰符详解,final修饰方法
  4. webClient 利用代理连接Rss资源
  5. hive导数据到mysql 自增主键出错_老大问我:“建表为啥还设置个自增 id ?用流水号当主键不正好么?”...
  6. [转]pthread用于进程间通信
  7. ActivityGroup自我堆栈管理(复用现有activity)
  8. 【C++】源自指针的报错
  9. sum() over() 函数的使用
  10. boost::io::quoted用法的测试程序
  11. 基类使用私有数据_C++作业之多继承与虚基类
  12. c++图的创建_「PS抠图系列13」通道混合器
  13. 在Windows Server2012系统中安装Oracle11g
  14. 蓝字冲销是什么意思_会计做帐中用红字和蓝字代表的意思是什么
  15. 人工智能剥夺就业岗位?不妨听听马斯克是如何建议的
  16. Linux命令行上程序执行的那一刹那!
  17. Hadoop-day07(MapReduce三个小案例)
  18. 朝花夕拾 - jsliang 大白前端新年庆
  19. 微信步数日历打卡小程序
  20. Papers with Code一个查找论文和对应代码的神器

热门文章

  1. P2P常见名词的解释
  2. Cadence Allegro自动放置所有元件图文教程及视频演示
  3. Chains (链 )
  4. 软文营销拒绝一成不变用故事建立情感依恋
  5. 服务器证书已过期,WebSphere应用服务器证书过期问题解决
  6. dsp31段最佳调音图_DSP调音技术~DSP功放31段EQ详解~DSP调音师推荐
  7. poi设置excel行高
  8. 华硕k5555l拆解图解_【多图】【教程】华硕K555L笔记本拆机除尘图解,通用此类模具所有笔记本...
  9. FB和FF MIC的用途
  10. 白话VPB(volume parameter block)