• Where to use Core Haptics

    • 포지션

      • 이벤트 기반의 오디오 및 햅틱 렌더링 API
      • 기존 API(AVAudioPlayer, UIFeedbackGenerator)와는 별개로 돌아간다.

      스크린샷 2022-06-23 오후 8.06.10.png

    • 지원 기기

      • 햅틱 엔진을 내장하고 있는 아이폰은 모두 동일한 API로 지원 → 아이폰 8부터
      • 이 엔진은 옛날 상업용 액츄에이터 아니고 애플이 직접 디자인한 탭틱 엔진이다.
    • 이 API가 필요한 사람들

      • UIFeedbackGenerator의 대체제는 아니다.
        • 정확히는 UIKit이 Core Haptics를 쓰는 방식이다.
        • 이 API도 iOS 13에서 개선이 있었으니 살펴보라.
      • Core Haptics는 오디오 햅틱 패턴을 커스텀 하고 싶어하는 사람들에게 필요한 것이다.
        • timestamp를 받아서 특정 시점에 재생하도록 할 수 있다.
        • 이를 통해서 Core Animation이나 AVAudioEngine의 sound event등과 동기화할 수 있다.
        • 좀 더 다양하게 재생 및 조율이 가능하다.
    • Core Haptic는 Audio API기도 하다.

      • Audio 재생을 Haptic과 동기화시켜서 돌리는 것
    • 애플은 이미 이러한 오디오 햅틱 경험을 여러군데 적용하고 있다.

      • 햅택 홈버튼, 햅틱 크라운, UIDatePicker 등…
      • 느끼지 못했을 수도 있지만 오디오는 이러한 경험에서 필수적이다.
      • Core Haptics를 쓰면 동일하게 만들 수 있다.
      • 게임, AR같은 곳에서도 유용할 것이다.
  • Expressing content

    • 컨텐츠 클래스
      • CHHapticEvent
        • Core Haptics에서 컨텐츠 요소의 기본 단위
        • 타입과 시간을 가지고 선택적으로 커스터마이징이 가능한 매개변수들(CHHpaticParameter)을 가짐
          • 타입은 haptic과 audio로 나뉘고, 거기서도 2가지로 나뉜다.
            • hapticTransient: 순간적이고 즉각적인 햅틱.
            • hapticContinuous: transient보다는 길게 이어지는 햅틱.
            • audioContinuous: 특정 시간동안 특정 파형을 반복하는 오디오 타입.
            • audioCustom: 개발자가 원하는 오디오를 제공할 수 있는 타입.
        • 이벤트는 시간에 따라 여러 개가 겹칠 수 있고, 이 때는 이벤트가 섞인다.
      • CHHapticPattern
        • 여러개의 CHHapticEvent가 묶인 그룹
      • CHHapticParameter
        • HapticEvent를 커스터마이징
        • 종류
          • intensity
          • audioVolume
          • hapticSharpness
          • 그 외에도 많음
    • 재생용 클래스
      • CHHapticEngine
      • CHHpaticPatternPlayer
      • CHHapticAdvancedPatterPlayer
  • Our first haptics

    • 추천 플로우
      1. 햅틱 컨텐츠 생성(예시에서는 NSDictionary에서 CHHapticPattern을 만든다)
      2. CHHapticEngine 인스턴스 만들기.
      3. CHHapticPattenPlayer만들기. 이 타입은 한개의 Pattern과 엔진에 연관된다.
      4. CHHapticEngine 시작
      5. 엔진이 준비되면, player를 시작한다.
      6. 플레이어가 종료되는 것을 기다린다
      7. 엔진을 종료하거나 다음 패턴을 재생한다
    • 재생 모드
      • immediate 모드: 시스템에 패턴을 즉시 재생하라고 하는것
      • scheduled 모드: 절대 타임스탬프를 지정해서, 다른 시스템 요소와 동기화해서 재생하라 요청하는 것
    import UIKit
    import CoreHaptics
    import CoreMotion
    
    class ViewController: UIViewController, UICollisionBehaviorDelegate {
    	// ...
    
    	var engine: CHHapticEngine!
    	var engineNeedsStart = true
    
    	// ...
    
    	override func viewDidLoad() {
    		createAndStartHapticEngine()
    	}
    
    	private func createAndStartHapticEngine() {
    		do {
    			engine = try CHHapticEngine()
    			// stopeedHandler는 직접 멈추지 않았는데 다른 이유로 멈출 때 호출
    			engine stoppedHandler = { reason in
    				switch reason {
    					// ...
    				}
    
    				self.engineNeedsStart = true
    			}
    		} catch let error {
    			fatalError("Engine Creation Error: \\(error)")
    		}
    
    		do {
    			try engine.start()
    			
    			endingNeedsStart = false
    		} catch let error {
    				fatalError("Engine Start Error: \\(error)")
    		}
    	}
    	// ...
    	
    	func collisionBehavior(...) {
    		do {
    			// ...
    			let hapticPlayer = try playerForMagnitude(normalizedMagnitude)
    
    			// player인스턴스를 잡고 있지 않음에 주목
    			try hapticPalyer?.start(atTime: CHHapticTimeImmediate)
    			// ...
    		} catch {
    			// ...
    		}
    	}
    
    	private func playerForMagnitude(_ magnitude: Float) throws -> CHHapticPatternPlayer? {
    	// ...
    		let hapticEvent = CHHapticEvent(eventType: .hapticTransient, parameters: [
    			CHHapticEventParameter(parameterID: .hapticSharpness, value: sharpness),
    			CHHpaticEventParameter(parameterID: .hapticIntensity, value: intensity)
    		], relativeTime: 0)
    
    		let audioEvent = CHHapticEvent(eventType: .audioContinuous, parameters: [
    			CHHapticEventParameter(parameterID: .audioVolume, value: volume),
    			CHHpaticEventParameter(parameterID: .decayTime, value: decay),
    			CHHpaticEventParameter(parameterID: .sustained, value: 0)
    		], relativeTime: 0)
    
    		let pattern = try CHHapticPattern(events: [hapticEvent, audioEvent], parameters: [])
    		return try engine.makePlayer(with: pattern)
    	}
    }
    
  • Dynamic parameters

    • 현재 존재하는 모든 이벤트와 앞으로 올 이벤트들의 parameter를 조절할 수 있는 기능
    • 지정된 timestape에 영향을 주게 되고, 여러개 Dynamic Parameter를 동시에 적용하거나 임의대로 적용할 수도 있다.
    • 예시) 게임에서 대사가 나올 때는 효과를 줄인다던지
  • Apple Haptic Audio Pattern(AHAP)

    • 텍스트 포맷으로 표현된 Core Haptics 패턴

    • 중첩된 Key-Value 쌍의 형태

      • JSON에서 쓰는 스키마 형태라서 Codable로도 읽을 수 있다.
    • 예시

      {
      	"Version": 1.0,
      	"Pattern": [
      		{
      			"Event": {
      				"Time": 0.0,
      				"EventType": "HapticTransient",
      				"EventParameters": [
      						{ "ParameterID": "HapticIntensity", "ParameterValue": 0.8 },
      						{ "ParameterID": "HapticSharpness", "ParameterValue": 0.4 }
      				] 
      			}
      		},
      		{
      			"Event": {
      				"Time": 0.5,
      				"EventType": "HapticContinuous",
      				"EventDuration": 0.25,
      				"EventParameters": [
      						{ "ParameterID": "HapticIntensity", "ParameterValue": 0.8 },
      						{ "ParameterID": "HapticSharpness", "ParameterValue": 0.4 }
      				] 
      			}
      		}
      	]
      }
      
  • 세션에서 다루는 내용은 일부고, 자세한 건 공식 문서와 샘플 코드를 참조할 것.

    • HIG에도 관련 내용이 있으니 참고하기 좋다.