블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2795)
Unity3D (852)
Programming (478)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (185)
협업 (61)
3DS Max (3)
Game (12)
Utility (68)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

[펌] Toon Shader

Unity3D/Shader / 2021. 3. 30. 13:50

You will learn to write a lit toon shader from scratch. The shader will be lit by a single directional light, and cast and receive shadows.

Toon shading (often called cel shading) is a rendering style designed to make 3D surfaces emulate 2D, flat surfaces. This style entered the mainstream with games like Jet Set Radio and The Wind Waker.

This tutorial will describe step-by-step how to write a toon shader in Unity. The shader will receive light from a single directional source, and have specular reflections and rim lighting. We will use the art style of The Legend of Zelda: Breath of the Wild as our reference, although we will not implement some of the more complex rendering techniques used in the game.

Breath of the Wild divides surfaces into two bands of lightness, adding rim and specular on top. The rim is only applied to surfaces illuminated by the main directional light.

The completed project is provided at the end of the article. Note that it also contains a large amount of comments in the created shader file to aid understanding.

Prerequisites

To complete this tutorial, you will need a working knowledge of Unity engine, and a basic understanding of shader syntax and functionality.

Download starter project .zip

These tutorials are made possible, and kept free and open source, by your support. If you enjoy them, please consider becoming my patron through Patreon.

 

Getting started

Download the starter project provided above and open it in the Unity editor. Open the Main scene, and open the Toon shader in your preferred code editor.

This file contains a simple shader that outputs a sampled texture, tinted by a color (with the default color set to cornflower blue). We will build off this file to create our toon shader.

1. Directional lighting

When writing shaders in Unity that interact with lighting it is common to use Surface Shaders. Surface shaders use code generation to automate the object's interaction with lights and global illumination. However, as our shader will only interact with a single directional light, it will not be necessary to use surface shaders.

We will set up our shader to receive lighting data. Add the following code at the top of the Pass, just after its opening curly brace.

Tags { "LightMode" = "ForwardBase" "PassFlags" = "OnlyDirectional" }

The first line requests some lighting data to be passed into our shader, while the second line further requests to restrict this data to only the main directional light. You can read more about Pass tags here.

To calculate our lighting, we will use a common shading model called Blinn-Phong, and apply some additional filters to give it a toon look. The first step is to calculate the amount of light received by the surface from the main directional light. The amount of light is proportional to the direction, or normal of the surface with respect to the light direction.

Blinn-Phong shading vectors, where L is the vector to the light source and N is the normal of the surface.

We'll need access to the object's normal data within our shader. Add the following code.

// Inside the appdata struct. float3 normal : NORMAL;// Inside the v2f struct. float3 worldNormal : NORMAL;

The normals in appdata are populated automatically, while values in v2f must be manually populated in the vertex shader. As well, we want to transform the normal from object space to world space, as the light's direction is provided in world space. Add the following line to the vertex shader.

o.worldNormal = UnityObjectToWorldNormal(v.normal);

With the world normal now available in the fragment shader, we can compare it to the light's direction using the Dot Product.

The dot product takes in two vectors (of any length) and returns a single number. When the vectors are parallel in the same direction and are unit vectors (vectors of length 1), this number is 1. When they are perpendicular, it returns 0. As you move a vector away from parallel—towards perpendicular—the dot product result will move from 1 to 0 non-linearly. Note that when the angle between the vectors is greater than 90, the dot product will be negative.

Add the following to the fragment shader. Note that existing code that is modified will be highlighted in yellow. New code is not highlighted.

// At the top of the fragment shader. float3 normal = normalize(i.worldNormal); float NdotL = dot(_WorldSpaceLightPos0, normal);// Modify the existing return line. return _Color * sample * NdotL;

This has rendered out a realistic style of illumination. To modify it to be toon-like, we will divide the lighting into two bands: light and dark.

// Below the NdotL declaration. float lightIntensity = NdotL > 0 ? 1 : 0; … return _Color * sample * lightIntensity;

What if we wanted more than two discrete bands of shading?

2. Ambient light

This looks good, but the dark side is too dark; right now it is completely black. Also, the edge between dark and light looks a bit sharp, but we'll deal with that later. For now, we will add ambient light.

Ambient light represents light that bounces off the surfaces of objects in the area and is scattered in the atmosphere. We will model it as a light that affects all surfaces equally and is additive to the main directional light.

// Add as a new property. [HDR] _AmbientColor("Ambient Color", Color) = (0.4,0.4,0.4,1)// Matching variable, add above the fragment shader. float4 _AmbientColor; … return _Color * sample * (_AmbientColor + lightIntensity);

You'll notice that modifying the intensity or color of the Directional Light in the scene does not affect our shader. We will add some code to include this in our lighting calculations.

What does [HDR] mean above the _AmbientColor property?

// Add below the existing #include "UnityCG.cginc" #include "Lighting.cginc"// Add below the lightIntensity declaration. float4 light = lightIntensity * _LightColor0;return _Color * sample * (_AmbientColor + light);

We multiply our existing lightIntensity value and store it in a float4, so that we include the light's color in our calculation. _LightColor0 is the color of the main directional light. It is a fixed4 declared in the Lighting.cginc file, so we include the file above to make use of the value.

Before going further, we'll soften the edge between light and dark to remove the jaggedness. Right now, the transition from light to dark is immediate and occurs over a single pixel. Instead, we'll smoothly blend the value from one to zero, using the smoothstep function.

smoothstep takes in three values: a lower bound, an upper bound and a value expected to be between these two bounds. smoothstep returns a value between 0 and 1 based on how far this third value is between the bounds. (If it is outside the lower or upper bound, smoothstep returns a 0 or 1, respectively).

Comparison between smoothstep (left) and a linear function (right). The values are mapped to the greyscale background, as well as the curves in red.

smoothstep is not linear: as the value moves from 0 to 0.5, it accelerates, and as it moves from 0.5 to 1, it decelerates. This makes it ideal for smoothly blending values, which is how we'll use it to blend our light intensity value.

float lightIntensity = smoothstep(0, 0.01, NdotL);

Our lower and upper bounds, 0 and 0.01, are very close together—this helps maintain a relatively sharp, toony edge. When NdotL is above 0.01 or below 0 it returns one and zero like before, respectively. However, in between that range it will smoothly blend between 0 and 1.

3. Specular reflection

Specular reflection models the individual, distinct reflections made by light sources. This reflection is view dependent, in that it is affected by the angle that the surface is viewed at. We will calculate the world view direction in the vertex shader and pass it into the fragment shader. This is the direction from the current vertex towards the camera.

// Add to the v2f struct. float3 viewDir : TEXCOORD1;// Add to the vertex shader. o.viewDir = WorldSpaceViewDir(v.vertex);

We'll now implement the specular component of Blinn-Phong. This calculation takes in two properties from the surface, a specular color that tints the reflection, and a glossiness that controls the size of the reflection.

// Add as new properties. [HDR] _SpecularColor("Specular Color", Color) = (0.9,0.9,0.9,1) _Glossiness("Glossiness", Float) = 32// Matching variables. float _Glossiness; float4 _SpecularColor;

The strength of the specular reflection is defined in Blinn-Phong as the dot product between the normal of the surface and the half vector. The half vector is a vector between the viewing direction and the light source; we can obtain this by summing those two vectors and normalizing the result.

// Add to the fragment shader, above the line sampling _MainTex. float3 viewDir = normalize(i.viewDir); float3 halfVector = normalize(_WorldSpaceLightPos0 + viewDir); float NdotH = dot(normal, halfVector); float specularIntensity = pow(NdotH * lightIntensity, _Glossiness * _Glossiness);return _Color * sample * (_AmbientColor + light + specularIntensity);

We control the size of the specular reflection using the pow function. We multiply NdotH by lightIntensity to ensure that the reflection is only drawn when the surface is lit. Note that _Glossiness is multiplied by itself to allow smaller values in the material editor to have a larger effect, and make it easier to work with the shader.

Once again we will use smoothstep to toonify the reflection, and multiply the final output by the _SpecularColor.

// Add below the specularIntensity declaration. float specularIntensitySmooth = smoothstep(0.005, 0.01, specularIntensity); float4 specular = specularIntensitySmooth * _SpecularColor;return _Color * sample * (_AmbientColor + light + specular);

4. Rim lighting

Rim lighting is the addition of illumination to the edges of an object to simulate reflected light or backlighting. It is especially useful for toon shaders to help the object's silhouette stand out among the flat shaded surfaces.

The "rim" of an object will be defined as surfaces that are facing away from the camera. We will therefore calculate the rim by taking the dot product of the normal and the view direction, and inverting it.

// In the fragment shader, below the line declaring specular. float4 rimDot = 1 - dot(viewDir, normal);return _Color * sample * (_AmbientColor + light + specular + rimDot);

Once again, we'll toonify the effect by thresholding the value with smoothstep.

// Add as new properties. [HDR] _RimColor("Rim Color", Color) = (1,1,1,1) _RimAmount("Rim Amount", Range(0, 1)) = 0.716// Matching variables. float4 _RimColor; float _RimAmount;// Add below the line declaring rimDot. float rimIntensity = smoothstep(_RimAmount - 0.01, _RimAmount + 0.01, rimDot); float4 rim = rimIntensity * _RimColor;return _Color * sample * (_AmbientColor + light + specular + rim);

With the rim being drawn around the entire object, it tends to resemble an outline more than a lighting effect. We'll modify it to only appear on the illuminated surfaces of the object.

// Add above the existing rimIntensity declaration, replacing it. float rimIntensity = rimDot * NdotL; rimIntensity = smoothstep(_RimAmount - 0.01, _RimAmount + 0.01, rimIntensity);

This is better, but it would be useful to be able to control how far the rim extends along the lit surface. We'll use the pow function to scale the rim.

// Add as a new property. _RimThreshold("Rim Threshold", Range(0, 1)) = 0.1// Matching variable. float _RimThreshold;float rimIntensity = rimDot * pow(NdotL, _RimThreshold);

5. Shadows

As a final step, we will add the ability for our shader to cast and receive shadows. Shadow casting is very simple. Add the following line of code below the entire Pass (outside the curly braces).

// Insert just after the closing curly brace of the existing Pass. UsePass "Legacy Shaders/VertexLit/SHADOWCASTER"

UsePass grabs a pass from a different shader and inserts it into our shader. In this case, we are adding a pass that is used by Unity during the shadow casting step of the rendering process.

In order to receive shadows, we will need to know in the fragment shader whether a surface is in a shadow or not, and factor that in to our illumination calculation. To sample the shadow map cast by a light, we'll need to transfer texture coordinates from the vertex shader to the fragment shader.

// As a new include, below the existing ones. #include "AutoLight.cginc"// Add to the v2f struct. SHADOW_COORDS(2)// Add to the vertex shader. TRANSFER_SHADOW(o)

We include Autolight.cginc, a file that contains several macros we will use to sample shadows. SHADOW_COORDS(2) generates a 4-dimensional value with varying precision (depending on the target platform) and assigns it to the TEXCOORD semantic at the provided index (in our case, 2).

TRANSFER_SHADOW transforms the input vertex's space to the shadow map's space, and then stores it in the SHADOW_COORD we declared.

Before we can sample the shadow map, however, we need to ensure our shader is set up to handle two different lighting cases: when the main directional light does and does not cast shadows. Unity will help us handle these two configurations by compiled multiple variants of this shader for each use case. You can read more about shader variants here. We will use a built-in shortcut to compile our variants. Add the following line of code just below the #pragma fragment frag line.

#pragma multi_compile_fwdbase

This shortcut instructs Unity to compile all variants necessary for forward base rendering. We can now sample the value in the shadow map, and apply it to our lighting calculation.

// In the fragment shader, above the existing lightIntensity declaration. float shadow = SHADOW_ATTENUATION(i); float lightIntensity = smoothstep(0, 0.01, NdotL * shadow);

SHADOW_ATTENUATION is a macro that returns a value between 0 and 1, where 0 indicates no shadow and 1 is fully shadowed. We multiply NdotL by this value, as it is the variable that stores how much light we received from the main directional light.

Conclusion

Toon shaders come in a wide variety of graphical styles, but achieving the effect usually centers around taking a standard lighting setup (as we did with Blinn-Phong) and applying a step function to it. In fact, when normals and lighting data is available it can be done as a post process effect. An example of this can be found in this tutorial for Unreal Engine 4.

View source GitHub repository

Leave me a message

Send me some feedback about the tutorial in the form below. I'll get back to you as soon as I can! You can alternatively message me through Twitter or Reddit.

 

 

[출처] roystan.net/articles/toon-shader.html

 

Unity Toon Shader Tutorial at Roystan

Learn to write a toon shader for Unity engine with specular reflections, rim lighting and shadow casting.

roystan.net

 

반응형
Posted by blueasa
, |

[링크] darkcatgame.tistory.com/27

 

Unity Cel Shading - 카툰렌더링

Cel Shading은 3D 오브젝트에 외각선을 강조하고, 명암을 표현 할 때 그라데이션이 아닌 단계별로 표현하여 만화 같은 느낌을 내는 것으로 Toon Shading, Cartoon Rendering이라고도 불린다. 대표적인 Cel Sha

darkcatgame.tistory.com

 

반응형
Posted by blueasa
, |

[링크1] blog.naver.com/buwhak/221238104504

 

synology 시놀로지 218+ plex 설정하기

218+ 세팅을 하면서 가장 스트레스 받고 힘들었던 plex 설정이다 ㅠㅠ​대체적으로 218+에서 plex로 웬만한...

blog.naver.com

[링크2] hospital82.tistory.com/93

 

시놀로지 패키지 활용 #4 - NAS 안에 있는 동영상 파일을 스트리밍해서 보자, PLEX

안녕하세요, 남두오성입니다. 이제 슬슬 시놀로지 NAS가 익숙해 지시면서, "내가 왜 이고생을 사서 하고 있나...." 라는 생각이 드실수도 있는 때가 되었습니다. 하지만, 와이프에게 "이럴려고 이

hospital82.tistory.com

[링크3] www.clien.net/service/board/kin/13197295

 

Plex 라이브러리 추가가 안됩니다. : 클리앙

시놀로지 718+ 사용중입니다. NAS에 Plex Media Server 설치하고... 설정 / 서버에서 원격접속 확인됐습니다. 초록색 체크표시도 뜨구요. 이 상태에서, 라이브러리 추가를 하면... 폴더에 volume1이라는 폴

www.clien.net

Plex 라이브러리 추가가 안될 때 >> 제어판 - 공유폴더 - 사용하는Video의 폴더 편집 - 권한 - 시스템 내부 사용자 탭 - PlexMediaServer 에 읽기/쓰기 권한을 주시면됩니다.

반응형
Posted by blueasa
, |

[링크1] seeit.kr/2087

 

시놀로지 나스 admin 계정 비밀번호 초기화 방법

시놀로지 나스 admin 계정 비밀번호 초기화 방법 최근 해외에서 시놀로지 나스에 랜섬웨어 공격이 많이 들어온다는 소식을 접했습니다. 그래서 바로 admin 계정으로 접속하여 비밀번호를 대문자,

seeit.kr

[링크2] blog.naver.com/cmtes_inc/220806084869

 

시놀로지NAS DS1815+ 비밀번호 분실로 관리자계정 초기화하다.

시놀로지NAS DS1815+ 비밀번호 분실로 관리자계정 초기화오늘은 시놀로지NAS DS1815+ 비밀번호 ...

blog.naver.com

 

반응형
Posted by blueasa
, |

[증상]

Unity 2019에서 Android API 29를 쓰다가 API 30으로 올려서 Android SDK API 30을 받으려고 하는데 실패하고 아래와 같은 에러메시지가 떴다.

 

Exception: Unable to install additional SDK platform. Please run the SDK Manager manually to make sure you have the latest set of tools and the required platforms installed. 
C:/Program Files/Unity/Hub/Editor/2019.4.22f1/Editor/Data/PlaybackEngines/AndroidPlayer\SDK\tools\bin\sdkmanager.bat "platforms;android-30", exit code 1

그래서 에러메시지에 있는 sdkmanager.bat 파일을 열어보니 JAVA_HOME 환경변수를 쓰고 있다.

요즘 Unity는 OpenJDK를 내장해서 각자 버전별로 쓰고 있기 때문에 환경변수를 만들지 않는데 내부 소스(sdkmanager.bat)에선 여전히 쓰게 해놓은 건 문제인 듯 하다.

 

아무튼 sdkmanager.bat가 돌려면 JAVA_HOME 환경변수를 만들어 줘야되니,

유니티 엔진 내부에 있던 OpenJDK를 C:\ 최상위에 하나 복사하고 JAVA_HOME으로 환경변수 만들어주니 잘 작동한다.

 

[유니티 엔진 내부 OpenJDK 위치] C:\Program Files\Unity\Hub\Editor\2019.4.22f1\Editor\Data\PlaybackEngines\AndroidPlayer\OpenJDK

[복사해서 옮긴 위치] C:\OpenJDK

 

[환경변수 셋팅] JAVA_HOME = C:\OpenJDK

 

 

[OpenJDK 시스템 환경변수 설정하기] codedragon.tistory.com/8510

 

OpenJDK - 시스템 환경 변수 설정하기

OpenJDK 설치하기 - openJDK https://codedragon.tistory.com/8774 OpenJDK - 시스템 환경 변수 설정하기 ·      JDK경로 확인하기 ·      JDK경로를 시스템 변수로 등록하기 ·      정상등록..

codedragon.tistory.com

 

 

[참조] forum.unity.com/threads/failed-to-update-android-sdk-package-list-unity-2019-2-10f1.869152/

 

Failed to update Android SDK Package List - Unity 2019.2.10f1

When I try to export the game build for the Android platform, I started getting this error: [ATTACH] Within the Project Settings - Minimum API Level...

forum.unity.com

 

반응형
Posted by blueasa
, |

 

 

SourceTree에서 History 항목의 한글 깨짐 현상을 수정하는 방법에 대해 알아봅니다.

 

 

 

1. SourceTree 한글 설정.

 

SourceTree의 일반 메뉴에 대해 한글 설정은 옵션에서 할 수 있습니다.

 

도구 -> 옵션으로 이동 후 Repo Settings 그룹 박스 내에 있는 언어와 기본 텍스트 인코딩을 변경해주면 됩니다.

 

 

위와 같이 설정 후 SourceTree를 재시작해 주시면 됩니다.

 

 

 

2. History의 커밋 메시지 한글화.

 

위와 같이 설정해도 History내부의 한글은 여전히 깨져있는 상태입니다.

 

 

이 현상은 각 워크 스페이스마다의 설정을 변경해 주어야 합니다.

 

워크스페이스 우측 상단에 보이는 설정을 클릭합니다.

 

 

이후 저장소 설정 화면이 나타날텐데 "설정 파일 편집..."을 선택한 뒤 텍스트 편집기로 config파일을 엽니다.

 

기본 config 파일은 아마 다음과 같을겁니다.

 

[core]
	repositoryformatversion = 0
	filemode = false
	bare = false
	logallrefupdates = true
	ignorecase = true
[remote "origin"]
	url = https://github.com/....git
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
	remote = origin
	merge = refs/heads/master

 

이 설정을 다음과 같이 수정해 줍시다.

 

[i18n]
    logOutputEncoding = euc-kr
    commitEncoding = UTF-8
[core]
	repositoryformatversion = 0
	filemode = false
	bare = false
	logallrefupdates = true
	ignorecase = true
[remote "origin"]
	url = https://github.com/....git
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
	remote = origin
	merge = refs/heads/master

 

이후 config파일을 저장 한 뒤 저장소 설정의 확인 버튼을 클릭합니다.

 

 

정상적으로 한글이 노출되는 것을 확인할 수 있습니다.

 



출처: https://smoh.tistory.com/346 [Simple is Beautiful.]

 

[Sourcetree] History 한글 깨짐 현상 수정

SourceTree에서 History 항목의 한글 깨짐 현상을 수정하는 방법에 대해 알아봅니다. 1. SourceTree 한글 설정. SourceTree의 일반 메뉴에 대해 한글 설정은 옵션에서 할 수 있습니다. 도구 -> 옵션으로 이동

smoh.tistory.com

 

 
반응형
Posted by blueasa
, |

증상

유니티 안드로이드 빌드 시 아래와 같은 에러

/Users/jim/Desktop/workspace/project/project/Temp/gradleOut/launcher/build/intermediates/merged_manifests/release/AndroidManifest.xml:52: AAPT: error: unexpected element found in

 

해당 파일의 52번째 줄에는 <quries>라는 신택스가 있는데 인식을 못하는 것 같다.

 

원인

stackoverflow.com/questions/62969917/how-do-i-fix-unexpected-element-queries-found-in-manifest

 

How Do I Fix "unexpected element found in "?

All of a sudden, I am getting this build error in my Android project: unexpected element found in How do I fix it?

stackoverflow.com

 

유니티의 gradle 버전이 3.4.0 인데 버전이 낮아서 그렇다고 한다.

 

해결

Gradle 버전 3.4.0 -> 3.4.3으로 변경한다.

위의 Grade의 com.android.tools.build:gradle:3.4.0'라고 적혀있는 부분을 com.android.tools.build:gradle:3.4.3'으로 바꿔주고 유니티 빌드를 다시 해보자.

 

위 파일의 경로는 아래와 같다.

/Applications/Unity/Hub/Editor/2019.4.15f1/PlaybackEngines/AndroidPlayer/Tools/GradleTemplates/baseProjectTemplate.gradle



출처: https://ajh322.tistory.com/294 [IT 잡동사니]

 

유니티 안드로이드 빌드 에러 - unexpected element found in

증상 유니티 안드로이드 빌드 시 아래와 같은 에러 /Users/jim/Desktop/workspace/project/project/Temp/gradleOut/launcher/build/intermediates/merged_manifests/release/AndroidManifest.xml:52: AAPT: error:..

ajh322.tistory.com

 

[참조] devgod.tistory.com/33

 

[Unity/Android] unexpected element found in 에러 해결

기존 프로젝트에 광고관련 SDK와 추가 스토어 대응을 하려고 플러그인을 이것저것 넣다보니 위와 같은 에러가 발생했다. 해당 에러는 구글에서 핫픽스가 나와있는 에러이며, 안드로이드 11에 관

devgod.tistory.com

[추가]

- 유니티 엔진 자체 Gradle 파일 위치는 기본 설치 시 아래와 같다.

[Unity 2018] C:\Program Files\Unity\Hub\Editor\2018.4.32f1\Editor\Data\PlaybackEngines\AndroidPlayer\Tools\GradleTemplates\mainTemplate.gradle

[Unity 2019] C:\Program Files\Unity\Hub\Editor\2019.4.22f1\Editor\Data\PlaybackEngines\AndroidPlayer\Tools\GradleTemplates\baseProjectTemplate.gradle

 

- Custom Gradle을 수정하려면 아래 파일에서 수정하자.

[Unity 2018]

1) Player Settings-Publishing Settings-Build-Custom Gradle Template 체크

2) ..\MyProject\Assets\Plugins\Android\mainTemplate.gradle 수정

 

[Unity 2019]

1) Project Settings-Player-Publishing Settings-Build-Custom Base Gradle Template 체크

2) ..\MyProject\Assets\Plugins\Android\baseProjectTemplate.gradle 수정

반응형
Posted by blueasa
, |

​With Apple’s incoming changes to the requirements for use of IDFA and needing to request users permission via App Tracking Transparency popup which is incoming at some point in early 2021. Apps need to start to prepare to the incoming changes.

​So how do you add a IDFA App Tracking Transparency popup from a Unity app?

At the moment there is no build in Unity method that will trigger the notification, There is however a preview package!

​As a note App Tracking Transparency is only required on IOS 14 devices, Altough this won’t causing issues on any lower OS version it won’t trigger the popup. If you don’t have access to a IOS 14 device you can test this with the XCode Emulators.​

1. Download Unity IOS Support Package

​Download the com.unity.ads.ios.support library from Github. This is current in preview and won’t be found directly from the package manager.

Unzip this into a folder outside your Asset Folder.

​Note it is best to make sure these files are checking into source control we will be using a relative path from Unity package manager.​

2. Add to Package Manager

​Now in you’re unity project go Windows->Package Manger.

​​

Then press the plus button and add from disk and navigate to the package.json file within the com.unity.ads.ios.support that we just unzipped.

​​

Unity will then import the package, Because we have imported the file from within the base Unity Project file the file has been direct to a relative path, if you however place this file outside this folder you will need to edit the Packages/manifest.json file to make it relative.

​​

​​

3. Triggering App Tracking Transparency Request

​As most SDK recommend We will need to trigger this before we initialize any SDK’s that we wish to pass the IDFA into. We also can only trigger this one pre install with users being able to edit there preference within the IOS Settings menu.​​Here we are using a really simple system where we trigger the notification when a user press a button.

Breaking down

​We first state we are using the IosSupport Library. We also inclosing this with a UNITY_IOS pre-compile which means we will only compile this code if we are running on IOS

#if UNITY_IOS using Unity.Advertisement.IosSupport; #endif

Next the actual triggering, again inclosing this with the UNITY_IOS pre-compile. We first check call ATTrackingStatusBinding.GetAuthorizationTrackingStatus() which will tell if the user has already set there preference, then ATTrackingStatusBinding.RequestAuthorizationTracking() Which will trigger the popup.

#if UNITY_IOS if(ATTrackingStatusBinding.GetAuthorizationTrackingStatus() == ATTrackingStatusBinding.AuthorizationTrackingStatus.NOT_DETERMINED) { ATTrackingStatusBinding.RequestAuthorizationTracking(); } #endif

4. Post build steps

​Like any other permission request Apple requires a description on why you are requesting these permission. For this we need to add the NSUserTrackingUsageDescription key to our PList. Instead of having to do this each time we create a build we are going to create a post build step that automatically adds it to the XCode Project

​You can see more about Unity post build steps here

using UnityEditor;
using UnityEditor.Callbacks;
#if UNITY_IOS
using UnityEditor.iOS.Xcode;
#endif
using System.IO;
 
public class PostBuildStep
{
/// <summary>
/// Description for IDFA request notification
/// [sets NSUserTrackingUsageDescription]
/// </summary>
const string TrackingDescription =
"This identifier will be used to deliver personalized ads to you. ";
 
[PostProcessBuild(0)]
public static void OnPostprocessBuild(BuildTarget buildTarget, string pathToXcode)
{
if (buildTarget == BuildTarget.iOS)
{
AddPListValues(pathToXcode);
}
}
 
static void AddPListValues(string pathToXcode)
{
// Get Plist from Xcode project
string plistPath = pathToXcode + "/Info.plist";
 
// Read in Plist
PlistDocument plistObj = new PlistDocument();
plistObj.ReadFromString(File.ReadAllText(plistPath));
 
// set values from the root obj
PlistElementDict plistRoot = plistObj.root;
 
// Set value in plist
plistRoot.SetString("NSUserTrackingUsageDescription", TrackingDescription);
 
// save
File.WriteAllText(plistPath, plistObj.WriteToString());
}
 
}

view rawPostBuild.cs hosted with ❤ by GitHub

​Here we just read in the PlistFile from the Xcode project we just created, then add in a new string values​plistRoot.SetString(“NSUserTrackingUsageDescription”, TrackingDescription);​Which sets the our popup text.​​

4. Testing it out

​Build the App to Xcode as normal and open it up in Xcode. If you open up the Info.Plist you will see the description we just added in from the post build step

​​​​

Now we can just build and play on our device. Then just press the button and you should see the IDFA Popup!

​​​​​

​​​​

​You will notice that if you press the button again it won’t re-trigger this is by the apple requirements so we will need to uninstall and pre-install to test it again.​

​This is the basic implementation ahead of the requirement of App Tracking Transparency for IOS, for a production version it may be best to pre-warn users about the popup, explaining why you are wanting to use the IDFA. This will likely improve the number of user who opt-in​

If any problems feel free to drop me a line on Twitter @Gamereat.

 

 

[출처] alanyeats.com/post/unityapptrackingtransparencypopup/

 

App Tracking Transparency in Unity (IDFA Popup) | Alan Yeats | Pocket Sized Hands Co-Founder | VR / AR Developer

​ With Apple’s incoming changes to the requirements for use of IDFA and needing to request users permission via App Tracking Transparency popup which is incoming at some point in early 2021. Apps need to start to prepare to the incoming changes. ​ So

alanyeats.com

 

반응형
Posted by blueasa
, |

[링크] unitylist.com/

 

UnityList

Search, explore and discover thousands of open source Unity assets with ease

unitylist.com

 

반응형
Posted by blueasa
, |

Re: UI Label line count

« Reply #5 on: July 19, 2013, 07:04:08 PM »

Just count instances of '\n' in the UILabel.processedText

 

 

[출처] www.tasharen.com/forum/index.php?topic=4509.0

 

UI Label line count

how can i get the total number of lines which will be required to show the label if it is limited with max line count. i will try and explain this more suppose i have a label which has suppose 40 lines, now to make label look small i set the Max Line var f

www.tasharen.com

 

[참조] devkorea.co.kr/bbs/board.php?bo_table=m03_qna&wr_id=42437

 

데브코리아

한국 게임개발자 커뮤니티

devkorea.co.kr

 
반응형
Posted by blueasa
, |