【游戏仿真实验】Unity仿真蒲丰投针实验,丢针计算圆周率,丢了一百万次针得出的结果是...
文章目录
- 一、前言
- 二、制作场景
- 1、制作针模型
- 2、桌面制作
- 3、平行线制作
- 三、物理仿真
- 1、桌面无反弹
- 2、针掉落
- 3、针滚动问题
- 4、针架到平行线上的问题
- 5、针与针相互影响的问题
- 四、UI界面
- 五、编写代码
- 1、针脚本
- 2、对象池
- 3、入口脚本
- 六、运行测试
- 七、工程源码
- 八、完毕
一、前言
嗨,大家好,我是新发。
我有个后端同事去面试的时候被问到了 蒲丰投针问题,可能有少部分同学没听过蒲丰投针问题,我这里简单科普一下。
假设桌面上画满间隔均为DDD的平行直线,向桌面任意投放一根长为LLL(L<DL<DL<D)的针,可以通过几何概型的计算得出:针与某直线相交的概率为:
P=2LπDP = \frac{2L}{πD} P=πD2L
当L=0.5DL = 0.5DL=0.5D时,
P=2LπD=DπD=1πP = \frac{2L}{πD} = \frac{D}{πD} = \frac{1}{π} \quad\quad P=πD2L=πDD=π1
也就是说,在L=0.5DL = 0.5DL=0.5D的情况下,我们总共投了MMM根针,有NNN根针与平行线相交,则
1P≈MN≈π\frac{1}{P} \approx \frac{M}{N} \approx π \quad\quad P1≈NM≈π
证明过程网上有很多,这里我就不展开了,我今天要做的,就是使用Unity
来对这个实验进行仿真,看看实验结果是不是与理论一致,我在网上没有看到有人使用Unity
做过蒲丰投针的仿真实验,那我就来做全网第一人吧~
二、制作场景
1、制作针模型
Unity
创建一个工程,在Hiererchy
面板空白处点击鼠标右键,点击菜单3D Object / Cylinder
,创建一个圆柱体,
如下
调整Scale
缩放,让它变成一个很细的圆柱体,
如下:
创建个材质球,调为红色,赋给它,这样看起来显眼一点,效果如下:
2、桌面制作
创建一个Cube
,
如下
调整Scale
的x
和z
,让它成为一个大桌面,
3、平行线制作
也是使用圆柱体,拉长,然后等间距排列即可,确保间距是针的长度的两倍,效果如下:
三、物理仿真
1、桌面无反弹
我希望针掉落到桌面时不要有弹跳,我们制作一个物理材质,
在Project
面板空白处右键鼠标,点击菜单Create / Physic Material
,
设置动态阻力和静态阻力为100
,弹性为0
,Friction Combine
和Bounce Combine
都设置为Minimum
,
把物理材质赋值给桌面的碰撞体组件的Material
属性,如下,
2、针掉落
给针添加Rigidbody
组件,
这样针就会收到重力作用而向下掉落,如下:
3、针滚动问题
我们看到针掉到桌面时,会滚动,
这是因为帧本身的角阻力太小,我们选中针物体,把它的Rigidbody
的角阻力设置为100
,
可以看到掉到桌面后不会滚动了,不过躺平时也会受到角阻力作用,
没关系,我们确保阵掉落的姿势与桌面平行就好了,
4、针架到平行线上的问题
我们看到,当帧落到平行线上时,会架在平行线上,
只需要把平行线弄成触发器就可以了,
效果如下:
5、针与针相互影响的问题
当一根针掉落在另一根针上时,会相互影响,比如架在别的针身上,影响与平行线的检测,比如这样子,
这个问题怎么解决呢?我们给针单独做一个层,
添加一个needle
层,
把针设置为needle
层,
然后打开Project Settings
,进入Physics
,把碰撞矩阵里的needle
勾选去掉,
可以看到,针与针可以相互穿透,互不影响了,
四、UI界面
使用UGUI
简单做一下界面,如下
五、编写代码
1、针脚本
创建一个Needle.cs
脚本,编写碰撞检测逻辑,逻辑很简单,我都写了注释,大家应该能看懂,
using UnityEngine;
using System;public class Needle : MonoBehaviour
{/// <summary>/// 碰撞到平行线回调/// </summary>public Action hitLineCb;/// <summary>/// 碰撞到地面回调/// </summary>public Action hitPlaneCb;private Rigidbody rig;/// <summary>/// 延迟回收/// </summary>private float delayHideTimer;/// <summary>/// 是否碰到了平行线/// </summary>private bool isHitedLine = false;private void Awake(){rig = GetComponent<Rigidbody>();}private void OnEnable(){delayHideTimer = 0f;rig.isKinematic = false;isHitedLine = false;}public void OnTriggerEnter(Collider collision){if (isHitedLine) return;// 碰到了平行线if("line" == collision.gameObject.tag){isHitedLine = true;hitLineCb?.Invoke();}}public void OnCollisionEnter(Collision collision){// 碰到了桌面if("plane" == collision.gameObject.tag){// 1秒后回收delayHideTimer = 1f;}}private void Update(){if (delayHideTimer > 0){delayHideTimer -= Time.deltaTime;if (delayHideTimer <= 0){hitPlaneCb?.Invoke();}}}
}
把Needle.cs
脚本挂到针物体上,
设置桌面的tag
为plane
,
设置平行线的tag
为line
,
2、对象池
因为要很高频地丢针,如果每次都创建销毁会比较浪费CPU
,所以我们写个对象池脚本:NeedlePool.cs
,代码如下:
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 对象池
/// </summary>
public class NeedlePool
{/// <summary>/// 入池/// </summary>public void Enqueue(GameObject obj){objPool.Enqueue(obj);}/// <summary>/// 出池/// </summary>public GameObject Dequeue(){if (objPool.Count == 0) return null; return objPool.Dequeue();}private Queue<GameObject> objPool = new Queue<GameObject>();
}
3、入口脚本
创建Main.cs
作为入口脚本,实现交互和控制,代码如下:
using UnityEngine;
using UnityEngine.UI;public class Main : MonoBehaviour
{public Text totalCntText;public Text hitedCntText;public Text resultText;public GameObject needleObj;public Button startBtn;public Text btnStateText;private int totalCnt;private int hitedCnt;private float timer;private bool isStarted = false;// 对象池private NeedlePool pool = new NeedlePool();private void Awake(){needleObj.SetActive(false);}private void Start(){startBtn.onClick.AddListener(() => {isStarted = !isStarted;btnStateText.text = isStarted ? "停止" : "开始";});}void Update(){if (Input.GetMouseButtonDown(0)){// 鼠标点击,生成针GenNeedle();UpdateText();}if (isStarted){// 自动生成针timer += Time.deltaTime;if (timer > 0.03f){// 提高丢针数量,加快速度for (int i = 0; i < 7; ++i){GenNeedle();}UpdateText();timer = 0;}}}/// <summary>/// 生成针/// </summary>private void GenNeedle(){++totalCnt;var obj = pool.Dequeue();if(null == obj)obj = Instantiate(needleObj);var x = Random.Range(-100f, 100f);var y = 0.1f;var z = Random.Range(-60f, 60f);obj.transform.position = new Vector3(x, y, z);obj.transform.rotation = Quaternion.Euler(new Vector3(90, Random.Range(-360f, 360f), 0));obj.SetActive(true);var needle = obj.GetComponent<Needle>();needle.hitLineCb = () =>{++hitedCnt;UpdateText();};needle.hitPlaneCb = () => {obj.SetActive(false);pool.Enqueue(obj);};}/// <summary>/// 更新UI/// </summary>private void UpdateText(){totalCntText.text = totalCnt.ToString();hitedCntText.text = hitedCnt.ToString();if(0 != hitedCnt)resultText.text = ((float)totalCnt / hitedCnt).ToString("#0.00000");}
}
把Main.cs
脚本挂到MainPanel
上,并赋值成员对象,如下:
六、运行测试
运行Unity
,测试效果如下:
投了十万多针,
继续投针,投了一百万针,
与π
的理论值很接近啦,实验成功~
七、工程源码
本文工程我已上传到CODE CHINA
,感兴趣的同学可自行下载学习,
地址:https://codechina.csdn.net/linxinfa/UnityBuffonNeedlesGame
注:我使用的Unity
版本为Unity 2021.1.9f1c1 (64-bit)
八、完毕
好了,今天就到这里吧。
我是林新发:https://blog.csdn.net/linxinfa
原创不易,若转载请注明出处,感谢大家~
喜欢我的可以点赞、关注、收藏,如果有什么技术上的疑问,欢迎留言或私信,拜拜~
【游戏仿真实验】Unity仿真蒲丰投针实验,丢针计算圆周率,丢了一百万次针得出的结果是...相关推荐
- 蒲丰投针计算机模拟ppt,蒲丰投针实验模课件.doc
概率论与数理统计实验 蒲丰投针与蒙特卡罗法 班级 应数12级01班 学号 2012444086 姓名 张旭东 蒲丰投针与蒙特卡罗法 张旭东 2012444086 (重庆科技学院 数学与应用数学 ,重庆 ...
- 蒲丰投针问题的matlab仿真
吃饭的时候突然想到蒲丰投针问题. 在许多地方都遇到过此针,高中概统,大学概统,随机过程的概率部分,今天读Shannon的传记,他女儿不小心把针洒地上了. 问题描述: 在平面中有一组间隔为a的平行线,随 ...
- Matlab模拟蒲丰投针实验计算Π值
文章目录 1.前言 2.实验目的 3.实验原理 (1)问题描述 (2)问题求解 4.实验过程 5.实验结果 6.实验结论 7.Matlab代码 1.前言 学习了概率论,决定自己动手编程实现蒲丰投针实验 ...
- 蒲丰投针结果_只能用纸笔才能计算圆周率?蒲丰告诉你,投针游戏也可以
自从很久以前人们发现了存在圆周率π这个神奇的数字之后,便费尽一切心力来计算这个值.在那个数学工具比较匮乏的时代,人们能够做的就是根据圆周率的定义来计算.历史上,东西方几乎在同时发现了割圆术,虽然细节上 ...
- 强化学习 蒲丰投针实验 蒙特卡洛算法
目录 一.蒲丰投针实验 1.1背景故事 1.2原理介绍 二.蒙特卡洛方法 2.1方法介绍 2.2经验轨迹 2.3在线学习与离线学习 2.4数学原理 一.蒲丰投针实验 1.1背景故事 1777年,蒲丰请 ...
- 一文读懂蒲丰投针实验
这个博客源于概率论复习期间,蒙特卡罗方法的思想起源,这种求π\piπ的思路非常的巧妙 附:历史上用蒲丰投针实验估计圆周率的实验记录,来源 蒲丰投针 蒲丰投针实验是法国数学家.自然科学家"乔治 ...
- 蒲丰投针实验的一些理解
由于要做ppt这里把自己的代码先暂时放上来,不当之处请多指正! 实验过程: 1)取一张白纸,在上面画上许多条间距为a的平行线. 2) 取一根长度为l(l≤a) 的针,随机地向画有平行直线的纸上掷n次, ...
- 蒲丰投针计算机模拟ppt,蒙特卡罗模拟课件.ppt
<蒙特卡罗模拟课件.ppt>由会员分享,提供在线免费全文阅读可下载,此文档格式为ppt,更多相关<蒙特卡罗模拟课件.ppt>文档请在天天文库搜索. 1.蒙特卡洛模拟数学实验之前 ...
- R语言-蒲丰投针问题(向量化)
蒲丰投针问题的具体过程及推导可参考百科,此处不再赘述,这里仅给出模拟步骤和实现代码. 蒲丰投针试验的模拟步骤 设定试验总次数 NNN,成功次数m=0m = 0m=0,针的长度为hhh,平行线间的距离为 ...
最新文章
- 【73套】Epic Stock Media配乐音效素材合集包
- SharePoint 检测页面编辑模式
- 五年引用量最高的10大论文:Adam第一,Transfromer上榜!竟然没有ResNet?
- Shadow of Survival
- java socket聊天工具_java+socket 简易聊天工具
- 在web项目中发布jaxws
- 使用 Maven 执行 java main class(java应用程序)
- DevExpress.XtraBars.Ribbon控件使用系列 (1)创建Ribbon窗体
- TCP/IP数据包结构分析
- Tree Recovery(二叉树递归遍历+求后序遍历模板)
- object.prototype.call
- python设置tk退出_退出tkinter gui
- CSS 文本转换 text-transform属性
- 微博抽奖贴为什么到时间了不开奖_热搜第一!微博闹剧,锦鲤“信小呆”被这样处罚...
- 随想录(学校作业和工程代码)
- clickhouse算术函数
- 数据库宿舍管理系统MySQL表_数据库课程设计报告—宿舍管理系统.doc
- Mixgo CE初体验
- 局域网传输/共享大文件
- 小学计算机面试说课稿,小学信息技术面试说课稿(模板)