前期工作
设计思想
此次突如其来的新冠病毒疫情蔓延迅速,短短时间便蔓延全球。由于我国防控工作到位,民众团结,已经基本战胜了疫情。但我们作为学生,依然无法返回校园。因此,我们针对疫情进行校园仿真模拟,实时模拟病毒在校园内会如何传播,以及在不同防控手段下的传播效果。
技术方案
场景设计
对大学校园进行了简化设计,设计了操场、宿舍区、图书馆、教室、食堂、医院等基本功能设施,模拟学生在校园内的基本活动状况
人物设计
使用不同颜色的小球表示健康程度不同的学生
蓝色——健康
黄色——潜伏期无传染性
橙色——潜伏期有传染性
红色——发病
实现思路
模拟学生在校园中的日常活动,其中包括:去教室上课、去操场锻炼、去图书馆学习、去食堂吃饭、去医院和回宿舍。假设在学校开学后,有一位感染新冠肺炎并处于潜伏期的同学来到了学校,由于体温等指标正常,学校没有对其进行核酸检测,就这样这位携带新冠病毒的同学混进了人群中,和健康的同学一起上课、吃饭、锻炼等。
模拟的场景中,我们假设学生有四种状态:健康、潜伏期(无传染性)、潜伏期(有传染性)和发病。我们给发病和潜伏期的同学设置了不同的感染率,其中发病的同学的感染率大于潜伏期(有传染性)的同学。学生感染病毒后进入潜伏期,潜伏期随机设置为3-7天,潜伏期的前期不具有传染性,在发病的前两天内开始具有传染性。
当有学生被检测出新冠肺炎后,针对学生的四种状态设置了不同的应对措施。
(1) 学校不采取任何措施。
(2) 发病的同学进入校医院的隔离区进行隔离,与发病同学有接触的同学进行宿舍隔离。
(3) 发病的同学进入校医院的隔离区进行隔离,与发病同学有接触的同学进行宿舍隔离,同时大家佩戴口罩,勤洗手。
(4) 发病的同学进入校医院的隔离区进行隔离,全校的学生进行宿舍隔离,同时大家佩戴口罩,勤洗手。
针对上述不同的应对措施来观察学生整体的感染情况。同时通过设置对照组来检验戴口
罩、勤洗手等防疫措施对预防新冠肺炎的作用。
模拟学生在校园中的移动是通过unity中的NavMeshAgent自动寻路组件来实现的,在场景中规划好可以行走的路线,然后通过给多物体添加NavMeshAgent来指定运动的终点来实现学生移动的模仿。
核心代码
(1)一些变量的声明,包括学生进行移动的教室、食堂、医院、操场和图书馆,是否戴口罩、勤洗手,有学生发病时是否全部隔离,发病期每次接触的传播率和潜伏期每次接触的传播率,学生的状态等。
public class nav : MonoBehaviour
{
// Use this for initialization
public GameObject text;//天数的文字UI
public GameObject classroom;//教室目标寻路地点的空物体
public GameObject diningtarget;//食堂目标寻路地点的空物体
public GameObject geliTarget;//隔离区目标寻路地点的空物体
public GameObject playground;//操场目标寻路地点的空物体
public GameObject library;//图书馆目标寻路地点的空物体
public float infectionRateIncidence = 10.0f;//发病期每次接触传播率10%
public float infectionRateLatent = 5.2f;//潜伏期每次接触传播率5.2%
public bool mask = false;
public bool washHand = false;
public bool TotalIsolation = false;
private NavMeshAgent agent;
private Vector3 startPoint;//出生点 也就是宿舍的坑位
public int infected = 0;//0健康 1潜伏 2发病 3潜伏可传染
public int isGeli;//点击studet的prefab 在inspector界面手动改动 是否隔离 0不会自我隔离 1会在发病后自动去医院
private int emergeGeli = 0;//紧急状态 如果开启马上回宿舍并告诉所有碰到的人
Color orange = new Color(255f / 255f, 112f / 255f, 0f / 255f);
private Text mText;
private int cover = 999;//潜伏期 由于前面已经开始判断是否发病 只能用很大的数防止开局全体感染
private int infecDay = 999;//被感染日期
private int state = 0;
private int count = 8 * 60;//计数 按60fps算 就是8秒
private int day = 0;//第几天
(2)获取组件NavMeshAgent,记录出生复活点位置,如果戴口罩、勤洗手则降低接触的传播率。
void Start()
{
agent = GetComponent<NavMeshAgent>();//地形改动以后记得加static以及Navigation重新bake
mText = text.GetComponent<Text>();
startPoint = this.gameObject.transform.position;//记录出生复活点位置
//PlayerPrefs.SetInt("emergeGeli", 0);
if (mask)
{
infectionRateIncidence = infectionRateIncidence * 0.6f;
infectionRateLatent = infectionRateLatent * 0.6f;
}
if(washHand)
{
infectionRateIncidence = infectionRateIncidence * 0.7f;
infectionRateLatent = infectionRateLatent * 0.7f;
}
PlayerPrefs.SetInt("TotalIsolation", 0);
}
(3)判断被感染的学生是否进入潜伏期的有传染性阶段。根据学生的状态来设置不同的颜色:如果处于潜伏期且具有传染性则设为橙色,不具有传染性则设置为黄色,发病则设置为红色,健康状态为蓝色。通过count计数,来实现学生一天中去往不同场所的运动。并判断是否需要进行全体隔离。
void FixedUpdate()
{//注意是Fixed
if ((cover + infecDay - 2) <= day)//天亮了 如果潜伏可传染期到达 - 2 就是前两天有传染性
infected = 3;//橙色
if ((cover + infecDay) <= day)//如果发病期到达
infected = 2;//变红
if (infected == 1)//如果潜伏无传染性 则变黄
this.gameObject.GetComponent<Renderer>().material.color = Color.yellow;
else if (infected == 2)//如果发病 则变红
{
this.gameObject.GetComponent<Renderer>().material.color = Color.red;
PlayerPrefs.SetInt("TotalIsolation", 1);
}
else if (infected == 3)//如果潜伏有传染性 则变橙色
this.gameObject.GetComponent<Renderer>().material.color = orange;
count++;
if (count > 8 * 60 )//8*60个计数进这个函数一次
{
count = 0;
if (state == 0)//去教室、图书馆或操场
{
day++;
mText.text = day.ToString();
agent.enabled = true;
state = 1;
int i = Random.Range(0, 100);
if (i <= 30)//去图书馆
agent.destination = library.transform.position;
else if (i <= 60)//去操场
agent.destination = playground.transform.position;
else//去教室
agent.destination = classroom.transform.position;
}
else if (state == 1)//去食堂
{
agent.enabled = true;
state = 2;
agent.destination = diningtarget.transform.position;
}
else if (state == 2)//回宿舍
{
agent.enabled = true;
state = 0;
agent.destination = startPoint;
}
}
if (PlayerPrefs.GetInt("TotalIsolation") == 1 && TotalIsolation)
emergeGeli = 1;
if (infected == 2 && isGeli == 1)
{//如果开启自我隔离并且发病
agent.destination = geliTarget.transform.position;
SendMessage("geli");
}
if (infected != 2 && emergeGeli == 1 && isGeli == 1)//如果没发病并且进入紧急状态
agent.destination = startPoint;//回宿舍
}
(5)感染的学生与其他学生接触时,按照病毒传播率进行感染。同时判断是否需要进行隔离。
private void OnCollisionEnter(Collision collision)
{
if (collision.collider.tag == "stu")//如果碰上了其他学生
{
float i = Random.Range(0.0f, 100.0f);
if (i <= infectionRateIncidence && infected == 2)//发病期 传染率
collision.gameObject.SendMessage("inf");//告诉他 你被传染了!
if (i <= infectionRateLatent && infected == 3)//潜伏期 传染率
collision.gameObject.SendMessage("inf");
//Destroy (collision.collider.gameObject);
if (infected == 2 || emergeGeli == 1)//如果我发病了 或我知道有人发病了 我就告诉被碰的人 进入紧急状态
collision.gameObject.SendMessage("geli");
}
}
void inf()
{
if (infected == 0)
{//如果没被感染
infecDay = day;
cover = Random.Range(3, 7);//潜伏期
infected = 1;//进入潜伏期 此时无传染性
}
}
void geli()
{
emergeGeli = 1;//当他为1进入紧急状态 马上回宿舍瑟瑟发抖
}
模拟结果
模拟前提——一位潜伏期具有感染性的学生进入了校园
没有任何防控措施,大约5天所有人被感染
佩戴口罩,大约7天所有人被感染
在呼吁同学们注意卫生勤洗手、佩戴口罩,发现发病的学生及时进行隔离,有很多学生处于健康状态
通过校园疫情模拟,我们可以看到防控措施是十分重要的。在人多聚集的地方,还是要做好万分的准备。