惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
T
Tenable Blog
Webroot Blog
Webroot Blog
L
Lohrmann on Cybersecurity
S
Securelist
S
Schneier on Security
NISL@THU
NISL@THU
Know Your Adversary
Know Your Adversary
C
Cybersecurity and Infrastructure Security Agency CISA
T
The Exploit Database - CXSecurity.com
L
LINUX DO - 热门话题
C
CXSECURITY Database RSS Feed - CXSecurity.com
O
OpenAI News
I
Intezer
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
TaoSecurity Blog
TaoSecurity Blog
S
Secure Thoughts
Application and Cybersecurity Blog
Application and Cybersecurity Blog
P
Privacy International News Feed
H
Hacker News: Front Page
N
Netflix TechBlog - Medium
M
MIT News - Artificial intelligence
博客园 - Franky
PCI Perspectives
PCI Perspectives
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Microsoft Azure Blog
Microsoft Azure Blog
MongoDB | Blog
MongoDB | Blog
L
LangChain Blog
P
Proofpoint News Feed
S
Security Affairs
WordPress大学
WordPress大学
The Last Watchdog
The Last Watchdog
S
SegmentFault 最新的问题
小众软件
小众软件
F
Full Disclosure
博客园 - 叶小钗
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
The Blog of Author Tim Ferriss
Simon Willison's Weblog
Simon Willison's Weblog
P
Palo Alto Networks Blog
Security Latest
Security Latest
P
Proofpoint News Feed
月光博客
月光博客
T
Tailwind CSS Blog
Scott Helme
Scott Helme
Hacker News - Newest:
Hacker News - Newest: "LLM"
Google Online Security Blog
Google Online Security Blog
T
Threat Research - Cisco Blogs
Help Net Security
Help Net Security
Project Zero
Project Zero

元视角

.NET 生态下的 Agent 框架选型:从 ReAct 到原生推理 - 元视角 从「能用」到「好用」:LLM 流式响应实现方式的探索之路 - 元视角 当我用 2000 条聊天记录,让 AI 为我画一幅自画像 - 元视角 基于 Supabase 的 AI 应用开发探索 - 元视角 微博 × MCP:社交媒体新玩法解锁 - 元视角 四点钟海棠花未眠 - 元视角 Semantic Kernel × MCP:智能体的上下文增强探索 - 元视角 基于 K-Means 聚类分析实现人脸照片的快速分类 - 元视角 容器技术驱动下的代码沙箱实践与思考 - 元视角 温故而知新:后端通用查询方案的再思考 - 元视角 浅议 CancellationToken 在前后端协同取消场景中的应用 - 元视角 Semantic Kernel 视角下的 Text2SQL 实践与思考 - 元视角 关于 ChatGPT 的流式传输,你需要知道的一切 - 元视角 RAG 的是与非、Rewrite 和 Rerank - 元视角 使用 EFCore 和 PostgreSQL 实现向量存储及检索 - 元视角 基于 LLaMA 和 LangChain 实践本地 AI 知识库 - 元视角 使用 llama.cpp 在本地部署 AI 大模型的一次尝试 - 元视角 如何为 Git 配置多个 SSH Key - 元视角 C# 使用 LibUsbDotNet 实现 USB 设备检测 - 元视角 基于 C# 实现样式与数据分离的打印方案 - 元视角 基于 SVG 的图形交互方案实践 - 元视角 前端视频播放技术概览 - 元视角 温故而知新,再话 Python 动态导入 - 元视角 后 GPT 时代,NLP 不存在了? - 元视角 视频是不能 P 的系列:使用 Milvus 实现海量人脸快速检索 - 元视角 GDI+下字体大小自适应方案初探 - 元视角 小爱音箱集成 ChatGPT 的不完全教程 - 元视角 程序员视角下的三体世界随想 - 元视角 关于 Docker 容器配置信息的渐进式思考 - 元视角 在 Docker 容器内集成 Crontab 定时任务 - 元视角 为你的服务器集成 LDAP 认证 - 元视角 似花还似非花 - 元视角 视频是不能 P 的系列:使用 Dlib 实现人脸识别 - 元视角 浅议分布式链路追踪与日志的整合 - 元视角 关于 Git 大文件上传这件小事 - 元视角 .NET 进程内队列 Channel 的入门与应用 - 元视角 使用 Fody 实现 .NET 的静态编织 - 元视角 .NET Core + ELK 搭建可视化日志分析平台(下) - 元视角 聊一聊前端图片懒加载背后的故事 - 元视角 支持外部链接跳转的 Vue Router 扩展实现 - 元视角 视频是不能 P 的系列:OpenCV 和 Dlib 实现表情包 - 元视角 不得不说的 ASP.NET Core 集成测试 - 元视角 再议 DDD 视角下的 EFCore 与 领域事件 - 元视角 Vue.js 前端项目容器化部署实践极简教程 - 元视角 再见,人间四月天 - 元视角 Python 图像风格化迁移助力画家梦想 - 元视角 利用 ASP.NET Core 中的标头传播实现分布式链路追踪 - 元视角 利用 gRPC 实现文件的上传与下载 - 元视角 七种武器:延迟队列的原理和实现总结 - 元视角 gRPC 流式传输极简入门指南 - 元视角 Envoy 集成 Jaeger 实现分布式链路追踪 - 元视角 浅议非典型 Web 应用场景下的身份认证 - 元视角 gRPC 借助 Any 类型实现接口的泛化调用 - 元视角 分布式丛林探险系列之 Redis 集群模式 - 元视角 分布式丛林探险系列之 Redis 主从复制模式 - 元视角 通过 Python 预测 2021 年双十一交易额 - 元视角 gRPC 搭配 Swagger 实现微服务文档化 - 元视角 SSL/TLS 加密传输与数字证书的前世今生 - 元视角 使用 Python 自动识别防疫健康码 - 元视角 你不可不知的容器编排进阶技巧 - 元视角 ASP.NET Core 搭载 Envoy 实现 gRPC 服务代理 - 元视角 再话 AOP,从简化缓存操作说起 - 元视角 ASP.NET Core 搭载 Envoy 实现微服务身份认证(JWT) - 元视角 ASP.NET Core 搭载 Envoy 实现微服务的监控预警 - 元视角 ASP.NET Core 搭载 Envoy 实现微服务的反向代理 - 元视角 ASP.NET Core gRPC 打通前端世界的尝试 - 元视角 EFCore 实体命名约定库:EFCore.NamingConventions - 元视角 ASP.NET Core gRPC 集成 Polly 实现优雅重试 - 元视角 ASP.NET Core gRPC 健康检查的探索与实现 - 元视角 ASP.NET Core gRPC 拦截器的使用技巧分享 - 元视角 SnowNLP 使用自定义语料进行模型训练 - 元视角 使用 HttpMessageHandler 实现 HttpClient 请求管道自定义 - 元视角 ABP vNext 的实体与服务扩展技巧分享 - 元视角 ABP vNext 对接 Ant Design Vue 实现分页查询 - 元视角 源代码探案系列之 .NET Core 跨域中间件 CORS - 元视角 源代码探案系列之 .NET Core 限流中间件 AspNetCoreRateLimit - 元视角 源代码探案系列之 .NET Core 并发限制中间件 ConcurrencyLimiter - 元视角 通过 EmbededFileProvider 实现 Blazor 的静态文件访问 - 元视角 低代码,想说爱你不容易 - 元视角 记一次失败的 ThoughtWorks 面试经历 - 元视角 从 C# 1.0 到 C# 9.0,历代 C# 语言特性一览 - 元视角 通过 Python 分析 2020 年全年微博热搜数据 - 元视角 基于 Python 和 Selenium 实现 CSDN 一键三连自动化 - 元视角 使用多线程为你的 Python 爬虫提速的 N 种姿势,你会几种? - 元视角 实现网页长截图的常见思路总结 - 元视角 温故而知新,由 ADO.NET 与 Dapper 所联想到的 - 元视角 视频是不能 P 的系列:OpenCV 人脸检测 - 元视角 作为技术宅的我,是这样追鬼滅の刃的 - 元视角 使用 Python 抽取《半泽直树》原著小说人物关系 - 元视角 厉害了!打工人用 Python 分析西安市职位信息 - 元视角 使用 dotTrace 对 .NET 应用进行性能分析与优化 - 元视角 一道 HashSet 面试题引发的蝴蝶效应 - 元视角 基于选项模式实现.NET Core 的配置热更新 - 元视角 Dapper.Contrib 在 Oracle 环境下引发 ORA-00928 异常问题的解决 - 元视角 .NET Core 中对象池(Object Pool)的使用 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(下):EventBus 篇 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(中):RabbitMQ 篇 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(上):基础篇 - 元视角 记一次从已损坏的 Git 仓库中找回代码的经历 - 元视角 .NET Core 原生 DI 扩展之属性注入实现 - 元视角
使用 Unity3D 创建一个幸运转盘 - 元视角
飞鸿踏雪 · 2015-03-13 · via 元视角

今天我们来做点和游戏无关的事情吧!博主最近情绪一直比较低落,因为在找工作的过程中遇到了些挫折。当一个人内心缺乏斗志的时候,通常会难以静下心来认真地做事情,所以这段时间博主并不打算再去为大家分享新的游戏案例,希望大家能够谅解啊。

好了,博主今天想和大家分享的是一个叫做幸运转盘的案例。我们知道平时在节假日商场为了促销商品,通常都会推出诸如转盘抽奖这样的游戏。在学了概率以后,虽然我们都知道中奖是一个小概率事件,可是人们对买彩票中奖这样的事情仍然乐此不疲。就像腾讯通过今年的春晚成功地为微信支付培养了大量忠实用户一样,虽然大家抢红包抢到的钱都不算多,可是大家都还是愿意去抢红包啊。为什么呢?呵呵,不就图一乐嘛。好了,那么下面我们一起乐一乐吧,因为激动人心的抽奖环节就要开始了!

首先我们来看看在 Unity3D 中如何实现转盘抽奖:

转盘游戏示意图 转盘游戏示意图

从这张图片我们可以看出,转盘抽奖有两部分组成:转盘是可以旋转的、转盘指针是固定不动的。那么,好了,抽奖无非就是让转盘转起来然后再停下来嘛,直接给出代码:

using UnityEngine;
using System.Collections;

public class LuckyRoll : MonoBehaviour {

    //幸运转盘
    private Transform mRoolPanel;

    //初始旋转速度
    private float mInitSpeed;
    //速度变化值
    private float mDelta=0.5f;

    //转盘是否暂停
    private bool isPause=true;

    void Start () 
    {
        //获取转盘
        mRoolPanel = this.transform.FindChild("Background");
    }

    //开始抽奖
    public void OnClick()
    {
        if (isPause)
        {
            //随机生成一个初始速度
            mInitSpeed=Random.Range(100,500);
            //开始旋转
            isPause = false;
        }
    }

    void Update()
    {
        if(!isPause)
        {

            //转动转盘(-1为顺时针,1为逆时针)
            mRoolPanel.Rotate(new Vector3(0,0,-1) * mInitSpeed * Time.deltaTime);
            //让转动的速度缓缓降低
            mInitSpeed -= mDelta;
            //当转动的速度为0时转盘停止转动
            if (mInitSpeed <= 0)
            {
                //转动停止
                isPause = true;
            }
        }
    }
}

这里我们随机给出一个速度 mInitSpeed,然后让它按照 mDelta 的速率缓慢的减少,当 mInitSpeed 的数值为 0 时表示转盘停止转动。好了,我们来看看最后的效果:

转盘游戏演示 转盘游戏演示

从现在的效果来看,这个案例基本上成功了,所以以后如果碰到需要这种抽奖活动的场合,大家就可以跟美术协调好,快速地制作出这样一个幸运转盘来向身边的人们炫耀了。不过这个案例同样存在问题:

  • 基于随机数的转盘转动不受玩家控制,玩家无法参与到互动当中,可以考虑触摸操作,这样可以根据玩家的操作来模拟转动,提高游戏的真实性和可玩性。
  • 因为抽奖的结果是由美术设计在转盘上的,所以程序无法根据转盘停止后指针的位置直接判断出玩家抽奖的结果以及本次抽奖是否为有效的抽奖(指针恰好停留在两个扇形区域的分界线上)。
  • 因为这里转盘的旋转并没有严格地按照实际情况下转盘的受力情况来设计,因此可以说这个游戏中的概率分布可能不是均匀的,因此计算机里使用的随机数是伪随机数。

好了,暂时就发现这些问题,如果有朋友知道如何模拟触屏操作和阻尼运动,可以在这篇文章后面给我留言,今天的内容就是这样了,希望大家会喜欢!

2015 年 3 月 31 日更新

今天找到了关于转盘游戏概率设计的相关内容,所以经过整理后补充在这里:

首先,这种转盘游戏概率设计的前提是转盘固定不动,转盘指针绕中心位置旋转,与这篇文章中的恰好相反。如下图所示,在这个转盘游戏的设计中主要遵循基本的三角函数,这里以指针默认位置朝上来讲解该原理。如果指针的默认位置在其它位置上的,可以此类推。

转盘游戏示意图 转盘游戏示意图

x += xcosᶱ y += ycosᶱ

好了,现在我们就可以通过调整指针的角度来实现抽奖游戏了。比如我们将转盘平均分成 8 份,指针角度为 0 表示奖品 A,指针角度为 45 度表示奖品 B 等等,以此类推。这样的话,我们只要调整指针的角度就可以控制抽奖的结果。可是在实际生活中,指针不可能一次就指到对应的奖品上去,通常会在旋转若干圈后慢慢地停下来。因此我们可以使用下列公式:

指针角度 = 360 * 圈数 + (目标角度与初始角度的差值)

这里的圈数可以通过随机数来生成,这样可以让每次抽奖更加随机些,当然为了增加抽奖的真实感,我们可以采用这篇文章中提到的减速的方法来实现一个缓停的效果。那么问题来了,如果转盘上的奖项不是均匀分布的怎么呢?这种情况可以根据转盘上圆心角的大小为每一个奖项设定一个范围,然后在这个范围内随机生成一个角度来计算指针的角度,好了,下面给出代码实现:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class LuckyRoll2 : MonoBehaviour {

    //对奖项进行封装
    private class WrapItem
    {
        public WrapItem(string name, float rank, float ang1, float ang2)
        {
            this.ItemName = name;
            this.ItemRank = rank;
            this.MinAngle = ang1;
            this.MaxAngle  =ang2;
        }

        //奖项名称
        public string ItemName { get; set; }
        //奖项概率
        public float ItemRank { get; set; }
        //最大角度
        public float MaxAngle { get; set; }
        //最小角度
        public float MinAngle { get; set; }
    }

    
    //全部的奖项
    private List<WrapItem> allItems;
    void Start () 
    {
        //初始化奖品
        allItems = new List<WrapItem>()
        {
           //圆心角为5°,概率为10%,以此类推
            new WrapItem("奖品1", 10, 0, 30),
            new WrapItem("奖品2", 15, 30, 90),
            new WrapItem("奖品3", 20, 90, 165),
            new WrapItem("奖品4", 25, 165, 255),
            new WrapItem("奖品5", 30, 255, 360),
        };

        //模拟抽奖10次
        for (int i = 0; i < 10; i++ )
        {
            Debug.Log(Roll());
        }
    }
    
    /// <summary>
    /// 抽奖方法
    /// </summary>
    private string Roll()
    {
       //抽奖结果
       string result = "";
       //概率总精度为100
       float totalRank = 100;
       foreach(WrapItem item in allItems)
       {
          //产生一个0到100之间的随机数
          float random  = Random.Range(0,totalRank);
          //将该随机数和奖品的概率比较
          if(random <= item.ItemRank)
          {
             //抽奖结果
             result = item.ItemName;
             //为转盘指针随机生成旋转角度
             float angle = Random.Range(item.MinAngle, item.MaxAngle);
             //旋转转盘指针,此处略
             break;
          }else
          {
             totalRank -= item.ItemRank;
          }
       }
       return "抽奖结果为:" + result;
    }
}

好了,这里我们没有写转盘旋转的功能,这部分内容大家自己去实现好了,因为在 Unity3D 里面实现这样一个功能实在是太简单了。今天我们主要关注的内容是概率,所以我们重点对概率做了些研究,这里我们来讨论下算法中的概率计算问题,首先奖品 1、奖品 2、奖品 2、奖品 4、奖品 5 的概率分别为 10%、15%、20%、25%、30%,其概率之和为 100。因此

奖品 1:从 0~100 中随机抽取一个数,这个数值小于 10 的概率显然是 10%,这是第一轮数组遍历。

奖品 2:在第一轮数组遍历没有返回的情况下,进入第二轮遍历,此时从 0~90 中随机抽取一个数,其概率为:(1 - (10 / 100) * (15 / (100 - 10)) = 15%。同样的,抽到奖品 3 的概率为(1 - (25 / 100))*(20 / (100 - 25)) = 20%,以此类推。

好了,这部分内容终于补充到这篇文章里了,对于这个问题的研究基本上可以告一段落,不得不说概率对于游戏开发来说还是蛮重要的啊,有时间学习下数学吧,反正咱底子不弱啊,哈哈。

下面给出程序演示效果:

转盘游戏概率设计效果演示 转盘游戏概率设计效果演示

参考资料

大家快来玩转盘抽奖游戏(走在网页游戏开发的路上)(七) PHP + jQuery 实现转盘抽奖概率可任意调整